vercel/ai · error · NoObjectGeneratedError

No object generated: the model did not return a response.

Error message

No object generated: the model did not return a response.

What it means

Within a single skill, every attached file must have a unique normalized path, because files are written relative to the skill directory and duplicates would overwrite each other. validateACPSkills tracks normalized paths per skill and throws when the same path appears twice (note: paths differing only by './' or redundant segments normalize to the same value and still count as duplicates).

Source

Thrown at packages/ai/src/generate-object/generate-object.ts:426

        providerOptions,
        abortSignal,
        headers: headersWithUserAgent,
      }),
    );

    const responseData = {
      id: generateResult.response?.id ?? generateId(),
      timestamp: generateResult.response?.timestamp ?? currentDate(),
      modelId: generateResult.response?.modelId ?? model.modelId,
      headers: generateResult.response?.headers,
      body: generateResult.response?.body,
    };

    const text = extractTextContent(generateResult.content);
    const reasoning = extractReasoningContent(generateResult.content);

    if (text === undefined) {
      throw new NoObjectGeneratedError({
        message: 'No object generated: the model did not return a response.',
        response: responseData,
        usage: asLanguageModelUsage(generateResult.usage),
        finishReason: generateResult.finishReason.unified,
      });
    }

    const finishReason = generateResult.finishReason.unified;
    const usage = asLanguageModelUsage(generateResult.usage);
    const warnings = generateResult.warnings;
    const resultProviderMetadata = generateResult.providerMetadata;
    const request: Omit<LanguageModelRequestMetadata, 'messages'> =
      generateResult.request ?? {};
    const response: Omit<LanguageModelResponseMetadata, 'messages'> =
      responseData;

    logWarnings({
      warnings,

View on GitHub (pinned to 69428b1f8b)

Solutions

  1. Deduplicate the skill's files by normalized path before submitting (keep the last/ intended entry).
  2. Rename one of the conflicting files to a distinct relative path.
  3. Normalize each candidate path (posix normalize, strip leading './') and assert uniqueness in your loader.

Example fix

// before
files: [{ path: 'docs/guide.md' }, { path: './docs/guide.md' }]

// after
files: [{ path: 'docs/guide.md' }]
Defensive patterns

Strategy: validation

Validate before calling

import path from 'node:path';
function dedupeFiles(files: Array<{ path: string }>) {
  const seen = new Set<string>();
  return files.filter(f => {
    const norm = path.posix.normalize(f.path);
    if (seen.has(norm)) return false;
    seen.add(norm);
    return true;
  });
}
skills.forEach(s => { s.files = dedupeFiles(s.files ?? []); });

Try / catch

try {
  await agent.addSkills(skills);
} catch (error) {
  if (error instanceof Error && error.message.startsWith('Duplicate ACP skill file path')) {
    await agent.addSkills(skills.map(s => ({ ...s, files: dedupeFiles(s.files ?? []) })));
  } else {
    throw error;
  }
}

Prevention

When it happens

Trigger: Listing the same file path twice in one skill's files array, e.g. [{path:'a.md'},{path:'./a.md'}] or 'docs/x.md' vs 'docs/../docs/x.md', when passing skills to the ACP harness.

Common situations: Merging file lists from multiple sources without deduplication; a glob/scan that yields the same file twice; entries that look different but normalize to the same path.

Related errors


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