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.

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)

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.