diff --git a/backend/internal/service/opencode_go_usage.go b/backend/internal/service/opencode_go_usage.go index bb7b7d7cdb..2e96d3384b 100644 --- a/backend/internal/service/opencode_go_usage.go +++ b/backend/internal/service/opencode_go_usage.go @@ -779,7 +779,7 @@ func (s *OpenCodeGoUsageService) refreshLoadedAccount(ctx context.Context, accou return s.persistFailure(ctx, account, intervalMinutes, now, resp.StatusCode, "unauthorized", retryAfter(resp.Header, now), true) } if resp.StatusCode == http.StatusForbidden { - return s.persistFailure(ctx, account, intervalMinutes, now, resp.StatusCode, "OpenCode Go subscription required (403)", retryAfter(resp.Header, now), false) + return s.persistFailure(ctx, account, intervalMinutes, now, resp.StatusCode, "forbidden", retryAfter(resp.Header, now), false) } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return s.persistFailure(ctx, account, intervalMinutes, now, resp.StatusCode, "http_error", retryAfter(resp.Header, now), false) diff --git a/backend/internal/service/opencode_go_usage_test.go b/backend/internal/service/opencode_go_usage_test.go index 2afeb156c6..a775584260 100644 --- a/backend/internal/service/opencode_go_usage_test.go +++ b/backend/internal/service/opencode_go_usage_test.go @@ -320,7 +320,7 @@ func TestOpenCodeGoUsageRefresh401Unauthorized(t *testing.T) { require.True(t, openCodeGoUsageAutoRefreshEnabled(account)) } -func TestOpenCodeGoUsageRefresh403SubscriptionRequired(t *testing.T) { +func TestOpenCodeGoUsageRefresh403Forbidden(t *testing.T) { account := openCodeGoUsageAccount(7) repo := &openCodeGoUsageTestRepo{accounts: map[int64]*Account{7: account}} stub := &openCodeGoUsageHTTPStub{status: http.StatusForbidden} @@ -330,7 +330,7 @@ func TestOpenCodeGoUsageRefresh403SubscriptionRequired(t *testing.T) { require.NoError(t, err) require.Equal(t, OpenCodeGoUsageStatusFailed, state.Snapshot.Status) require.Equal(t, http.StatusForbidden, state.Snapshot.HTTPStatus) - require.Equal(t, "OpenCode Go subscription required (403)", state.Snapshot.LastError) + require.Equal(t, "forbidden", state.Snapshot.LastError) require.Equal(t, 1, state.Snapshot.FailureCount) } diff --git a/frontend/src/i18n/locales/en/admin/accounts.ts b/frontend/src/i18n/locales/en/admin/accounts.ts index d11d7a9e7f..7870e0e25a 100644 --- a/frontend/src/i18n/locales/en/admin/accounts.ts +++ b/frontend/src/i18n/locales/en/admin/accounts.ts @@ -203,7 +203,8 @@ export default { refreshSuccess: 'OpenCode Go usage refreshed', refreshFailed: 'Failed to refresh OpenCode Go usage', errors: { - OPENCODE_GO_USAGE_REFRESH_RATE_LIMITED: 'Refresh is limited. Try again in {retry_after_seconds} seconds.' + OPENCODE_GO_USAGE_REFRESH_RATE_LIMITED: 'Refresh is limited. Try again in {retry_after_seconds} seconds.', + forbidden: 'Upstream returned 403: could be a missing/expired OpenCode Go subscription or a WAF/access-policy block; check the network path and HTTP status.' } }, types: { diff --git a/frontend/src/i18n/locales/zh/admin/accounts.ts b/frontend/src/i18n/locales/zh/admin/accounts.ts index b002e5d54b..88560960c3 100644 --- a/frontend/src/i18n/locales/zh/admin/accounts.ts +++ b/frontend/src/i18n/locales/zh/admin/accounts.ts @@ -406,7 +406,8 @@ export default { refreshSuccess: 'OpenCode Go 用量已刷新', refreshFailed: '刷新 OpenCode Go 用量失败', errors: { - OPENCODE_GO_USAGE_REFRESH_RATE_LIMITED: '刷新过于频繁,请在 {retry_after_seconds} 秒后重试。' + OPENCODE_GO_USAGE_REFRESH_RATE_LIMITED: '刷新过于频繁,请在 {retry_after_seconds} 秒后重试。', + forbidden: '上游返回 403:可能是订阅缺失/失效,也可能是 WAF 或访问策略拦截,请结合网络路径与 HTTP 状态排查。' } }, types: {