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

  1. Regenerate the strict invocation descriptors against the current provider package and redeploy host and client together.
  2. Align package versions across the tree: run pnpm why <provider-package> and pnpm dedupe so a single provider version serves everyone.
  3. If you own the provider and consumers cannot be regenerated yet, restore the previous wire field name and re-release.
  4. 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

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.