decolua/9router · error

${this.provider} requires accountId in providerSpecificData

Error message

${this.provider} requires accountId in providerSpecificData

What it means

Top-level catch of the MITM request handler: any exception thrown while classifying/routing the request (body collection, host→tool resolution, isChatRequest, model extraction/mapping, or handler dispatch) returns HTTP 500 JSON with type "mitm_error". It is the last-resort wrapper around handler intercepts that themselves throw outside their own try/catch.

Source

Thrown at open-sse/executors/default.js:132

      return `${normalized}${path}`;
    }
    if (this.provider?.startsWith?.("anthropic-compatible-")) {
      const baseUrl = credentials?.providerSpecificData?.baseUrl || ANTHROPIC_COMPAT_BASE;
      const normalized = baseUrl.replace(/\/$/, "");
      return `${normalized}/messages`;
    }
    // gemini-format: build :streamGenerateContent / :generateContent path
    if (this.config.format === "gemini") {
      return `${this.config.baseUrl}/${model}:${stream ? "streamGenerateContent?alt=sse" : "generateContent"}`;
    }
    // urlSuffix (e.g. ?beta=true) declared per-provider in registry
    if (this.config.urlSuffix) {
      return `${this.config.baseUrl}${this.config.urlSuffix}`;
    }
    const url = this.config.baseUrl;
    if (url?.includes("{accountId}")) {
      const accountId = credentials?.providerSpecificData?.accountId;
      if (!accountId) throw new Error(`${this.provider} requires accountId in providerSpecificData`);
      return url.replace("{accountId}", accountId);
    }
    return url;
  }

  // Fallback descriptor for providers without an explicit entry in AUTH_DESCRIPTORS.
  resolveAuthDescriptor() {
    if (this.provider?.startsWith?.("anthropic-compatible-")) {
      return { apiKey: { header: "x-api-key", scheme: "raw" }, oauth: { header: "Authorization", scheme: "bearer" }, anthropicVersion: true };
    }
    if (this.config?.format === "claude") {
      return { ...XAPIKEY, anthropicVersion: true };
    }
    return BEARER;
  }

  buildHeaders(credentials, stream = true, url, model) {
    const rt = credentials?.runtimeTransport;

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read `Unhandled error: <msg>` in the MITM log to find the failing step.
  2. Retry the request; if reproducible, capture the request with the dumper/file log (ENABLE_FILE_LOG) to inspect the payload.
  3. Verify the client request path/headers match what the handler expects (tool updates can change request shapes).
  4. Update 9Router if the IDE shipped a new request format the extractor doesn't parse.
  5. As a workaround, exclude that tool's host from MITM interception so it passes through untouched.
Defensive patterns

Strategy: try-catch

Validate before calling

// sanity-check the request before sending through the MITM
if (!request.url || !request.headers.host) throw new Error('request missing url/host — MITM dispatcher will 500');

Try / catch

const res = await sendViaMitm(request);
if (res.status === 500) {
  const body = await res.json();
  if (body.error?.type === 'mitm_error') {
    // dispatcher-level failure — match `Unhandled error: <msg>` in MITM logs
    // and enable ENABLE_FILE_LOG to capture the offending payload
  }
}

Prevention

When it happens

Trigger: collectBodyRaw throws mid-read, getToolForHost/isChatRequest/extractModel/getMappedModel throw on an unexpected request shape, or handlers[tool].intercept rethrows (e.g. model is null where a mapped model was required).

Common situations: Malformed or truncated request bodies from the IDE; a tool handler with an unguarded code path; unexpected URL/header format after a tool update; bugs introduced when adding a new handler.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/fe39740e1d099e87. Report an issue: GitHub.