Skip to content

[bug]: OpenRouter free tier => 'Invalid openrouter-key-v1 response' (limit_remaining: null not handled) #244

Description

@log0u7

Summary

OpenRouter free-tier keys trigger Invalid openrouter-key-v1 response because the plugin does not handle limit_remaining: null when the API returns no usage limit.

Symptom

Running /quota with a valid OpenRouter free-tier key produces:

OpenRouter: Invalid openrouter-key-v1 response

The key is valid (verified via GET https://openrouter.ai/api/v1/key → HTTP 200), but the plugin rejects it.

Root Cause

In src/lib/quota-providers-remote.ts:684:

(remaining !== undefined && (typeof remaining !== "number" || !Number.isFinite(remaining)))

OpenRouter free-tier API returns:

{ "data": { "usage": 0.106921435, "limit": null, "limit_remaining": null } }
  • limit_remaining: null (not undefined)
  • null !== undefined → true
  • typeof null !== "number" → true
  • Condition fails → error message

The plugin already handles limit: null correctly (lines 681-682), but limit_remaining: null is not handled. No test covers this case.

Impact

  • OpenRouter free-tier users cannot use the plugin's budget tracking
  • False positive error for valid keys
  • Plugin appears broken for free-tier users

Proposed Fix

Patch src/lib/quota-providers-remote.ts:684:

// Before
(remaining !== undefined && (typeof remaining !== "number" || !Number.isFinite(remaining)))

// After
(remaining !== null && remaining !== undefined && (typeof remaining !== "number" || !Number.isFinite(remaining)))

Treat null as absent (consistent with limit handling).

Test Coverage

Add test case for free-tier response:

it("accepts OpenRouter free-tier (limit_remaining null)", async () => {
  vi.stubGlobal("fetch", vi.fn().mockResolvedValue(
    jsonResponse({ data: { usage: 0.1, limit: null, limit_remaining: null } })
  ));
  const result = await fetchRemoteQuotaProvider(source({ format: "openrouter-key-v1" }), "secret");
  expect(result.success).toBe(true);
  expect(result.entries[0].kind).toBe("spend"); // "Spend" instead of budget
});

Affected Versions

  • npm: @slkiser/opencode-quota@4.8.2 (latest)
  • GitHub: main branch (no fix yet)

Reproduction

# Using a free-tier key (limit_remaining: null)
curl https://openrouter.ai/api/v1/key -H "Authorization: Bearer <your-key>"
# → { "data": { "usage": 0.106921435, "limit": null, "limit_remaining": null } }

# Plugin rejects this response with "Invalid openrouter-key-v1 response"

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions