deepseek-ai/deepseek-harness · error · TypertGatewayError
provider-mismatch
provider-mismatch
Error message
Context provider ${JSON.stringify(invocation.context)} does not match its strict definition What it means
The descriptor records which wire field carries the context identity and, for strict codecs, the wire type symbol. resolveReceiverContext compares both against the live provider's wire and wireTypeSymbol and throws provider-mismatch when they differ: the invocation definition and the runtime provider were generated from different versions of the wire contract, so dispatch would read the wrong args field or validate the identity against the wrong type.
Source
Thrown at packages/api/gateway/src/index.ts:376
private async resolveReceiverContext(
descriptor: InvocationDescriptor,
args: Readonly<Record<string, unknown>>,
endpoint: string,
): Promise<Context> {
if (descriptor.invocation.kind === 'direct') return this.ctx
const invocation = descriptor.invocation
const provider = this.ctx.typert.contexts.getHost(invocation.context)
if (provider === undefined) {
throw new TypertGatewayError(
'context-unavailable',
endpoint,
`Context provider ${JSON.stringify(invocation.context)} is unavailable`,
)
}
if (provider.wire !== invocation.wire
|| (invocation.codec.mode === 'strict' && provider.wireTypeSymbol !== invocation.codec.typeSymbol)) {
throw new TypertGatewayError(
'provider-mismatch',
endpoint,
`Context provider ${JSON.stringify(invocation.context)} does not match its strict definition`,
{ field: invocation.wire },
)
}
const identity = decode(invocation.codec, args[invocation.wire], 'input-invalid', endpoint, invocation.wire)
let context: Context | undefined
try {
context = await provider.resolve(identity)
} catch (cause) {
if (cause instanceof TypertLookupFailure) throw cause
throw new TypertGatewayError(
'context-failed',
endpoint,
`Context provider ${JSON.stringify(invocation.context)} failed`,
{ cause, field: invocation.wire },
)View on GitHub (pinned to b150a551b8)
Solutions
- Regenerate the strict invocation descriptors against the current provider package and redeploy host and client together.
- Align package versions across the tree: run pnpm why <provider-package> and pnpm dedupe so a single provider version serves everyone.
- If you own the provider and consumers cannot be regenerated yet, restore the previous wire field name and re-release.
- Confirm which provider is actually live with typert.contexts.getHost(key) and compare its wire value with the descriptor's invocation.wire.
Example fix
// before — descriptor: invocation.wire = "sessionId"; live provider: wire = "ctxId" await gateway.invoke(request) // → provider-mismatch (field: sessionId) on every call // after — regenerate strict descriptors from the current provider package // so invocation.wire = "ctxId" matches, then redeploy both sides together
Defensive patterns
Strategy: validation
Validate before calling
import type { Context } from '@deepseek-ai/cordis'
import type { InvocationDescriptor } from '@deepseek-ai/dsh-typert-protocol'
// Cross-check a descriptor's context invocation against the live provider.
function contextProviderMatches(ctx: Context, descriptor: InvocationDescriptor): boolean {
if (descriptor.invocation.kind !== 'context') return true
const provider = ctx.typert.contexts.getHost(descriptor.invocation.context)
if (provider === undefined || provider.wire !== descriptor.invocation.wire) return false
return descriptor.invocation.codec.mode !== 'strict'
|| provider.wireTypeSymbol === descriptor.invocation.codec.typeSymbol
} Type guard
import { TypertGatewayError } from '@deepseek-ai/dsh-api-gateway'
function isProviderMismatch(error: unknown): error is TypertGatewayError {
return error instanceof TypertGatewayError && error.code === 'provider-mismatch'
} Try / catch
try {
await gateway.invoke(request)
} catch (error) {
if (error instanceof TypertGatewayError && error.code === 'provider-mismatch') {
// deployment skew: quarantine the endpoint until artifacts are regenerated
throw new Error(`stale wire contract on ${error.endpoint} (field ${error.field}); regenerate descriptors`)
}
throw error
} Prevention
- Ship generated strict descriptors and the provider package in one atomic version bump.
- Run a boot-time cross-check of every mounted descriptor's wire/typeSymbol against the live registries and fail startup on mismatch.
- Gate wire-field renames behind major releases that regenerate every consumer.
When it happens
Trigger: provider.wire !== invocation.wire — for example the descriptor says the identity rides 'sessionId' but the registered provider now declares 'ctxId' — or a strict descriptor whose codec.typeSymbol no longer equals provider.wireTypeSymbol after one side regenerated its type graph.
Common situations: Upgrading the provider package without regenerating client descriptors (or the reverse); renaming a context identity wire field in a release; two different versions of the same workspace package resolved inside one dependency tree so an old provider is registered.
Related errors
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/92eb284cfa3e754b.
Report an issue: GitHub.