continuedev/continue · error · Error

Unsupported tool type in Anthropic: ${tool.type}

Error message

Unsupported tool type in Anthropic: ${tool.type}

What it means

openaiToolToAnthropicTool only accepts tools with type 'function'. Any other OpenAI tool type reaches the else branch and throws with the offending type name. Anthropic's tool schema has no representation for non-function tool types.

Source

Thrown at packages/openai-adapters/src/apis/AnthropicUtils.ts:166

          return undefined; // TODO not supported yet
        case "function":
          return {
            type: "tool",
            name: toolChoice.function.name,
          };
      }
  }
}

export function openaiToolToAnthropicTool(tool: ChatCompletionTool): Tool {
  if (tool.type === "function" && "function" in tool) {
    return {
      name: tool.function.name,
      description: tool.function.description,
      input_schema: tool.function.parameters as Tool.InputSchema, // TODO unsafe cast, may be differences between openai tool schema and anthropic tool schema,
    };
  } else {
    throw new Error(`Unsupported tool type in Anthropic: ${tool.type}`);
  }
}

// Extract media type from data URL (ex. "data:image/png;base64,..." -> "image/png")
export function getAnthropicMediaTypeFromDataUrl(
  dataUrl: string,
): Base64ImageSource["media_type"] {
  const match = dataUrl.match(/^data:([^;]+);base64,/);
  if (match) {
    switch (match[1]) {
      case "image/png":
      case "image/gif":
      case "image/webp":
        return match[1];
    }
  }
  return "image/jpeg";
}

View on GitHub (pinned to 5522c6f44c)

Solutions

  1. Ensure every tool in the tools array has type:'function' with a valid function:{name,description,parameters}
  2. Filter out non-function tools before calling the adapter
  3. Validate tool definitions against the OpenAI function-tool schema before sending

Example fix

// before
const tools = [{ type: 'code_interpreter' }];
await api.chatCompletionNonStream({ model, messages, tools });

// after
const tools = [{ type: 'function', function: { name: 'get_weather', description: '...', parameters: { type: 'object', properties: {} } } }];
await api.chatCompletionNonStream({ model, messages, tools });
Defensive patterns

Strategy: validation

Validate before calling

const ok = tools.every(t => t.type === 'function' && t.function?.name);

Type guard

function isOpenAiFunctionTool(t: any): t is { type: 'function'; function: { name: string } } {
  return t?.type === 'function' && typeof t.function?.name === 'string';
}

Try / catch

try { return await api.chatCompletionNonStream({ ...body, tools }, signal); }
catch (e) { if (/Unsupported tool type/.test(String(e))) { throw new Error(`Filter non-function tools: ${e.message}`); } throw e; }

Prevention

When it happens

Trigger: Passing tools:[{type: 'custom'|'code_interpreter'|...}] in chatCompletionStream/NonStream to the Anthropic adapter; anything other than type:'function' triggers the throw.

Common situations: Reusing OpenAI tool definitions (e.g. with newer tool types) against Claude; malformed tool objects missing the type field (undefined type); providers emitting non-standard tool types.

Related errors


AI-assisted analysis of continuedev/continue@5522c6f44c (2026-08-27). Data as JSON: /api/errors/e1023501e99b5142. Report an issue: GitHub.