Skip to content

fix(auth/apikeys): fix 500 on API key create -- type assertion rejected cross-package request (closes #1440) - #1444

Merged
cristim merged 1 commit into
mainfrom
fix/1440-apikey-create-500
Jul 17, 2026
Merged

cristim merged 1 commit into
mainfrom
fix/1440-apikey-create-500

Conversation

@cristim

@cristim cristim commented Jul 17, 2026

Copy link
Copy Markdown
Member

Root cause

Service.CreateAPIKeyAPI in internal/auth/service_apikeys_api.go decoded the incoming request using a direct Go type assertion:

createReq, ok := req.(APICreateAPIKeyRequest)
if !ok {
    return nil, fmt.Errorf("invalid request type")
}

The HTTP handler (internal/api) unmarshals the JSON request body into api.CreateAPIKeyRequest, which is a distinct Go type in a different package. Even though both types carry identical json field tags (name, expires_at, permissions), Go's type system is nominal: the assertion req.(auth.APICreateAPIKeyRequest) always evaluates to false. Every call to POST /api/api-keys therefore returned "invalid request type", which bubbled up as a 500 "Failed to create API key: Internal server error".

The mock test (TestHandler_createAPIKey_Success) used mock.Anything so it never caught the type mismatch.

Fix

Replace the direct type assertion with a type switch:

  • Fast path: if the caller already passes auth.APICreateAPIKeyRequest (existing service tests, direct internal callers), use it directly with zero overhead.
  • Default path: JSON-encode the incoming value and decode it back into APICreateAPIKeyRequest. This accepts any struct with compatible json tags (api.CreateAPIKeyRequest, anonymous structs) without requiring cross-package imports.

Tests

  • New: TestService_CreateAPIKeyAPI_CrossPackageType passes an anonymous struct (same json tags, different Go type) and asserts success. This test fails against the pre-fix code.
  • Fixed: TestAuthServiceAdapter_CreateAPIKeyAPI in internal/server was missing GetUserByID and GetGroup mocks. The test silently passed before because the type assertion returned early before reaching those store calls. Now the full call chain executes and the mock setup is complete.

Closes

Closes #1440

Root cause: CreateAPIKeyAPI did req.(auth.APICreateAPIKeyRequest) to decode
the incoming request. The HTTP handler (internal/api package) unmarshals the
request body into api.CreateAPIKeyRequest - a distinct Go type that carries
the same json field names but is not auth.APICreateAPIKeyRequest. The type
assertion always failed, returning "invalid request type", which bubbled up
as a 500 "Internal server error" on every POST /api/api-keys call.

Fix: replace the direct type assertion with a type switch. The fast path
handles auth.APICreateAPIKeyRequest directly (existing service tests). The
default path JSON-encodes the incoming value and decodes it into
APICreateAPIKeyRequest; this accepts any struct whose json tags are compatible
(including api.CreateAPIKeyRequest), without requiring a cross-package import.

Also fix TestAuthServiceAdapter_CreateAPIKeyAPI in internal/server which was
missing GetUserByID and GetGroup mocks: the test silently passed before
because the type assertion failure returned early; now the full call chain
executes and the mocks must be complete.

Regression test: TestService_CreateAPIKeyAPI_CrossPackageType passes an
anonymous struct (same json tags, different Go type) to CreateAPIKeyAPI and
asserts success. This test would have failed against the pre-fix code.
@cristim cristim added triaged Item has been triaged priority/p1 Next up; this sprint severity/high Significant harm urgency/this-sprint Within the current sprint impact/many Affects most users effort/m Days type/bug Defect labels Jul 17, 2026
@cristim

cristim commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 11 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6fa90bc5-c71b-44d8-ae59-17d68cc1431e

📥 Commits

Reviewing files that changed from the base of the PR and between bef2d0e and 4c0883f.

📒 Files selected for processing (3)
  • internal/auth/service_apikeys_api.go
  • internal/auth/service_apikeys_api_test.go
  • internal/server/adapter_test.go
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1440-apikey-create-500

Comment @coderabbitai help to get the list of available commands.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@cristim

cristim commented Jul 17, 2026

Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026 •

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


You're currently rate limited under our Fair Usage Limits Policy. Your recent PR review activity is in the 95th percentile or higher among CodeRabbit users, so adaptive limits apply. Your next review will be available in 11 minutes.

@cristim
cristim merged commit ee676ae into main Jul 17, 2026
19 checks passed
@cristim
cristim deleted the fix/1440-apikey-create-500 branch July 27, 2026 11:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/m Days impact/many Affects most users priority/p1 Next up; this sprint severity/high Significant harm triaged Item has been triaged type/bug Defect urgency/this-sprint Within the current sprint

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(admin/apikeys): Create API Key returns 500 Internal server error

1 participant