Skip to main content
This page covers the most common problems developers run into when setting up and using @vibesjs/sdk.

Setup issues

Wrong registry: npm:@vibesjs/sdk

If you import from npm:@vibesjs/sdk instead of jsr:@vibesjs/sdk, the import resolves silently but produces no useful exports — the npm name is a placeholder stub. Fix: Always use the JSR registry.
// deno.json
{
  "imports": {
    "@vibesjs/sdk": "jsr:@vibesjs/sdk@^1.0"   // correct
  //  "@vibesjs/sdk": "npm:@vibesjs/sdk"        // wrong — stub package
  }
}
For Node.js, install via the JSR CLI:
npx jsr add @vibesjs/sdk

Zod version mismatch (v3 vs v4)

Vibes requires Zod v4. Installing zod without a version pin may give you Zod v3, which has a different API. Symptoms include TypeScript errors on z.object, z.string, and similar. Fix:
# Node.js
npm install zod@^4

# Deno — pin in your import map
"zod": "npm:zod@^4"

Missing API key

Every provider requires an API key set as an environment variable. If the key is absent, the provider throws a 401 or similar authentication error at runtime. Fix: Export the key before running your script:
export ANTHROPIC_API_KEY="sk-ant-..."   # Anthropic
export OPENAI_API_KEY="sk-..."          # OpenAI
export GOOGLE_GENERATIVE_AI_API_KEY="..." # Google
Never commit API keys to source control. Add .env to your .gitignore and use your deployment platform’s secret management in production.

Deno cache corruption

If Deno reports a missing export for a package that exists, a corrupted cache entry may be to blame. This can happen after a failed or partial download. Detect: The import resolves but z (or another export) is undefined at runtime. Fix: Clear the affected entry and re-run:
# Remove the specific package from Deno's npm cache
rm -rf ~/Library/Caches/deno/npm/registry.npmjs.org/<package>/<version>

# Deno re-fetches automatically on next run
deno run --allow-env --allow-net your_script.ts
Replace <package> and <version> with the affected package (e.g. zod/4.0.0).

Provider errors

APICallError / connection refused

This usually means the provider’s API is unreachable or the model name is incorrect. Check:
  1. Your API key is set and valid.
  2. The model string matches the provider’s naming (e.g. "claude-sonnet-4-6" for Anthropic, "gpt-4o" for OpenAI).
  3. You have network access from where the script runs.

Model not found

Passing an unrecognised model ID to a provider function causes the provider to reject the request.
// Wrong - invented model name
anthropic("claude-ultra-9000")

// Correct - check provider docs for valid model IDs
anthropic("claude-sonnet-4-6")

Understanding error classes

@vibesjs/sdk throws typed errors that you can catch and handle specifically. Import them from jsr:@vibesjs/sdk:
Error classWhen it is thrown
MaxTurnsErrorThe agent exceeded maxTurns without producing a final result
MaxRetriesErrorResult validation failed after all configured retries
UsageLimitErrorA token or request limit set via usageLimits was exceeded
ApprovalRequiredErrorA tool with requiresApproval: true was called and needs human sign-off
ModelRequestsDisabledErrorA real model call was made while setAllowModelRequests(false) is active in tests

Catching a specific error

import { Agent, MaxTurnsError, UsageLimitError } from "jsr:@vibesjs/sdk";

try {
  const result = await agent.run("Do a complex task");
  console.log(result.output);
} catch (err) {
  if (err instanceof MaxTurnsError) {
    console.error("Agent ran too long — increase maxTurns or simplify the task.");
  } else if (err instanceof UsageLimitError) {
    console.error(`Limit exceeded: ${err.limitKind} reached ${err.current} (limit: ${err.limit})`);
  } else {
    throw err; // re-throw unexpected errors
  }
}

UsageLimitError fields

When you catch a UsageLimitError, it carries three properties:
PropertyTypeDescription
limitKind"requests" | "inputTokens" | "outputTokens" | "totalTokens"Which limit was exceeded
currentnumberUsage at the point of failure
limitnumberThe configured cap

Debugging failed tool calls

When a tool call fails, the SDK feeds the error back to the model so it can retry or adjust. If failures persist, add logging inside your execute function:
import { tool } from "jsr:@vibesjs/sdk";
import { z } from "zod";

const myTool = tool({
  name: "my_tool",
  description: "Does something",
  parameters: z.object({ input: z.string() }),
  execute: async (_ctx, { input }) => {
    console.log("[my_tool] called with:", input);
    try {
      const result = await doSomething(input);
      console.log("[my_tool] result:", result);
      return result;
    } catch (err) {
      console.error("[my_tool] error:", err);
      throw err; // let the SDK handle the retry
    }
  },
});
Set maxRetries on a tool to control how many times the SDK retries a failing execution before propagating the error to the model as a permanent failure.

Common Zod schema mistakes

Using .optional() on required parameters

The model will not pass optional fields reliably. Prefer explicit defaults or separate tools.
// Avoid: model may omit the field unpredictably
parameters: z.object({ city: z.string().optional() })

// Better: always require it, let the model ask for clarification
parameters: z.object({ city: z.string().describe("City name, required") })

Forgetting .describe() on fields

Without descriptions, the model has no guidance on what each field means. Always add .describe() to every parameter.
// Missing descriptions
parameters: z.object({ q: z.string(), n: z.number() })

// With descriptions — much better model behaviour
parameters: z.object({
  q: z.string().describe("Search query"),
  n: z.number().describe("Maximum number of results to return"),
})

Overly deep or recursive schemas

Deeply nested or self-referential Zod schemas can cause providers to reject the generated JSON Schema. Keep tool parameters flat where possible.

Next steps

Getting Help

Where to ask questions and report bugs

Installation

Back to the installation guide