vercel/ai · error

maxEmbeddingsPerCall must be greater than 0

Error message

maxEmbeddingsPerCall must be greater than 0

What it means

validateACPSkills (run by materializeACPSkills before writing any files) requires every skill name to match /^[a-z0-9]+(?:-[a-z0-9]+)*$/ — a lowercase kebab-case slug — and not be '.' or '..'. Names with uppercase letters, underscores, spaces, or empty strings are rejected because skill names become directory names on disk.

Solutions

  1. Slugify the name to lowercase kebab-case: lowercase, replace underscores/spaces with '-', strip invalid characters.
  2. Collapse consecutive dashes and trim leading/trailing dashes.
  3. Validate all skill names with the kebab-case regex before submitting skills.

Example fix

// before
{ name: 'Code Reviewer', files: [...] }

// after
{ name: 'code-reviewer', files: [...] }
Defensive patterns

Strategy: validation

Validate before calling

const KEBAB = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
function slugify(name: string): string {
  return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
}
skills.forEach(s => { if (!KEBAB.test(s.name)) s.name = slugify(s.name) || 'skill'; });

Type guard

function isKebabCaseSlug(name: string): boolean {
  return /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name) && name !== '.' && name !== '..';
}

Try / catch

try {
  await agent.addSkills(skills);
} catch (error) {
  if (error instanceof Error && error.message.includes('expected a kebab-case slug')) {
    await agent.addSkills(skills.map(s => ({ ...s, name: slugify(s.name) })));
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Providing a HarnessV1Skill whose name is 'My Skill', 'my_skill', 'MySkill', '', '.', '..', or contains non-ASCII characters when passing skills to the ACP harness.

Common situations: Generating skill names from display names or titles; converting folder names with underscores to skills; user-authored skill configs that were never slugified.

Related errors


AI-assisted analysis of vercel/ai@69428b1f8b (2026-08-30). Data as JSON: /api/errors/9c92a2e7dd4d4506. Report an issue: GitHub.

Appendix: source

Thrown at packages/ai/src/embed/embed-many.ts:451

        throw error;
      }
    },
  });
}

const textEncoder = new TextEncoder();

function splitByEmbeddingLimits({
  values,
  maxEmbeddingsPerCall,
  maxInputBytesPerCall,
}: {
  values: Array<string>;
  maxEmbeddingsPerCall: number;
  maxInputBytesPerCall: number;
}): Array<Array<string>> {
  if (maxEmbeddingsPerCall <= 0) {
    throw new Error('maxEmbeddingsPerCall must be greater than 0');
  }

  if (maxInputBytesPerCall <= 0) {
    throw new Error('maxInputBytesPerCall must be greater than 0');
  }

  if (values.length === 0) {
    return [];
  }

  const chunks: Array<Array<string>> = [];
  let currentChunk: Array<string> = [];
  let currentInputBytes = 0;

  for (const value of values) {
    const inputBytes = textEncoder.encode(value).length;

    if (

View on GitHub (pinned to 69428b1f8b)