Skip to content

fix: exclude undefined cost from providerMetadata#359

Merged
robert-j-y merged 7 commits intomainfrom
devin/1769544841-fix-undefined-cost-in-provider-metadata
Jan 27, 2026
Merged

fix: exclude undefined cost from providerMetadata#359
robert-j-y merged 7 commits intomainfrom
devin/1769544841-fix-undefined-cost-in-provider-metadata

Conversation

@robert-j-y
Copy link
Contributor

@robert-j-y robert-j-y commented Jan 27, 2026

Description

Fixes #262 - When models like gemini-3-pro-preview don't return a cost value, the providerMetadata object was including cost: undefined. Since undefined is not a valid JSON value, this caused AI SDK validation failures when passing providerMetadata back into subsequent conversation turns.

Before:

providerMetadata: {
  openrouter: {
    usage: {
      promptTokens: 17,
      completionTokens: 227,
      totalTokens: 244,
      cost: undefined,  // ❌ Invalid JSON value
    }
  }
}

After:

providerMetadata: {
  openrouter: {
    provider: 'openai',  // Now included for consistency
    usage: {
      promptTokens: 17,
      completionTokens: 227,
      totalTokens: 244,
      // cost field omitted when undefined ✓
    }
  }
}

The fix uses conditional spreading/assignment to only include cost when it has a defined value, matching the existing pattern used for other optional fields like costDetails.

Changes Summary

  • Chat model: Conditional spreading for cost in both doGenerate and doStream
  • Completion model:
    • Added providerMetadata with schema validation in doGenerate (was missing entirely)
    • Added provider field tracking in doStream
    • Added provider field to completion schema
  • Embedding model:
    • Now always returns providerMetadata with full usage structure and schema validation via OpenRouterProviderMetadataSchema.parse()
    • Added provider field to schema

Updates since last revision

  • Added comprehensive test coverage for completion model's doGenerate providerMetadata:
    • should return providerMetadata with usage and provider - verifies basic structure
    • should omit cost from providerMetadata when undefined - verifies the main bug fix
    • should include cost: 0 in providerMetadata when cost is zero - verifies zero cost is preserved
    • should default provider to empty string when not returned by API - verifies fallback behavior
    • should include token details in providerMetadata when provided - verifies full feature coverage

Human Review Checklist

  • Verify cost: 0 is still correctly included (the != null check allows this)
  • Confirm all affected locations were fixed:
    • src/chat/index.ts - doGenerate (line ~485) and doStream (line ~703)
    • src/completion/index.ts - doGenerate (line ~224, uses schema validation) and doStream (line ~419, tracks provider)
    • src/embedding/index.ts - doEmbed (line ~93, uses schema validation)
  • Verify the behavioral changes are acceptable:
    • Embedding model now always returns providerMetadata with full structure (previously undefined when no cost)
    • Completion model doGenerate now returns providerMetadata with schema validation (previously didn't return it at all)
    • All models now include provider field (defaults to '' when not returned by API)
  • Note: doStream methods build metadata manually without schema validation (matches existing chat model pattern for streaming performance)

Link to Devin run: https://app.devin.ai/sessions/7543a73deec84146abe08abf555d19a9
Requested by: Robert Yeakel (@robert-j-y)

Checklist

  • I have run pnpm stylecheck and pnpm typecheck
  • I have run pnpm test and all tests pass
  • I have added tests for my changes (if applicable)
  • I have updated documentation (if applicable)

Changeset

  • I have run pnpm changeset to create a changeset file

When cost is undefined, it should not be included in the providerMetadata
object since undefined is not a valid JSON value. This was causing AI SDK
validation failures when passing providerMetadata back into subsequent
conversation turns.

The fix uses conditional spreading/assignment to only include the cost
field when it has a defined value, matching the existing pattern used
for other optional fields like costDetails.

Fixes #262

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
devin-ai-integration bot and others added 6 commits January 27, 2026 20:32
Ensure embedding model also uses conditional spreading for cost field
to maintain consistency with chat and completion models.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
For consistency with chat model and streaming endpoints, the completion
model's doGenerate method now returns providerMetadata with usage info.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
… models

- Completion doGenerate: use OpenRouterProviderMetadataSchema.parse() with provider field
- Completion doStream: track and include provider field in providerMetadata
- Completion schema: add provider field
- Embedding model: include provider field and full usage structure (promptTokens, completionTokens, totalTokens)
- Embedding schema: add provider field
- Update embedding test expectations

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>
@robert-j-y robert-j-y merged commit 85d6633 into main Jan 27, 2026
2 checks passed
@robert-j-y robert-j-y deleted the devin/1769544841-fix-undefined-cost-in-provider-metadata branch January 27, 2026 21:26
@github-actions github-actions bot mentioned this pull request Jan 27, 2026
kesavan-byte pushed a commit to osm-API/ai-sdk-provider that referenced this pull request Feb 13, 2026
* fix: exclude undefined cost from providerMetadata

When cost is undefined, it should not be included in the providerMetadata
object since undefined is not a valid JSON value. This was causing AI SDK
validation failures when passing providerMetadata back into subsequent
conversation turns.

The fix uses conditional spreading/assignment to only include the cost
field when it has a defined value, matching the existing pattern used
for other optional fields like costDetails.

Fixes OpenRouterTeam#262

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* fix: apply same cost fix to embedding model

Ensure embedding model also uses conditional spreading for cost field
to maintain consistency with chat and completion models.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* fix: add providerMetadata to completion model doGenerate

For consistency with chat model and streaming endpoints, the completion
model's doGenerate method now returns providerMetadata with usage info.

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* fix: add schema validation and provider field to completion/embedding models

- Completion doGenerate: use OpenRouterProviderMetadataSchema.parse() with provider field
- Completion doStream: track and include provider field in providerMetadata
- Completion schema: add provider field
- Embedding model: include provider field and full usage structure (promptTokens, completionTokens, totalTokens)
- Embedding schema: add provider field
- Update embedding test expectations

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* fix: add schema validation to embedding model for consistency

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

* test: add coverage for completion doGenerate providerMetadata

Co-Authored-By: Robert Yeakel <robert.yeakel@openrouter.ai>

---------

Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gemini-3-pro-preview returns undefined fields inside providerMetadata, causing ai-sdk validation failures

2 participants