EveryInc/compound-engineering-plugin · error · Error

Target ${targetName} did not return a bundle.

Error message

Target ${targetName} did not return a bundle.

What it means

After resolving the output root and scope, `run` calls `target.convert(plugin, options)` and expects a bundle object describing the converted output. A defensive check throws this error if the handler returns null/undefined. This is an internal contract failure — with the shipped converters it essentially never fires; it indicates a broken or partially-written target handler returning no bundle.

Source

Thrown at src/commands/convert.ts:167

    if (!target.implemented) {
      throw new Error(`Target ${targetName} is registered but not implemented yet.`)
    }

    const resolvedScope = validateScope(targetName, target, args.scope ? String(args.scope) : undefined)

    const primaryOutputRoot = resolveTargetOutputRoot({
      targetName,
      outputRoot,
      codexHome,
      piHome,
      pluginName: plugin.manifest.name,
      hasExplicitOutput,
      scope: resolvedScope,
    })
    const bundle = target.convert(plugin, options)
    if (!bundle) {
      throw new Error(`Target ${targetName} did not return a bundle.`)
    }

    const effectiveScope =
      targetName === "opencode" ? resolveOpenCodeWriteScope(hasExplicitOutput, resolvedScope) : resolvedScope
    await target.write(primaryOutputRoot, bundle, effectiveScope)
    console.log(`Converted ${plugin.manifest.name} to ${targetName} at ${primaryOutputRoot}`)

    const extraTargets = parseExtraTargets(args.also)
    const allTargets = [targetName, ...extraTargets]
    for (const extra of extraTargets) {
      const handler = targets[extra]
      if (!handler) {
        console.warn(`Skipping unknown target: ${extra}`)
        continue
      }
      if (!handler.implemented) {
        console.warn(`Skipping ${extra}: not implemented yet.`)
        continue

View on GitHub (pinned to c9c10f8c75)

Solutions

  1. Inspect the target's `convert` handler (src/targets/*.ts) and ensure it returns a bundle for all valid plugin inputs.
  2. Verify the source plugin loaded correctly (valid .claude-plugin/plugin.json, skills, etc.) — a converter may return null on unexpected input.
  3. If this fires on a stock target with an unmodified plugin, report it as a bug; it indicates a broken converter contract.

Example fix

// before (in a custom target handler)
convert: (plugin, options) => {
  if (plugin.manifest.name === "x") return
  ...
}
// after
convert: (plugin, options) => {
  if (plugin.manifest.name === "x") return buildEmptyBundle(plugin)
  ...
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { targets } from "./src/targets/index"
const handler = targets[targetName]
if (handler) {
  const bundle = handler.convert(plugin, options)
  if (!bundle) throw new Error(`${targetName}.convert returned no bundle for plugin ${plugin.manifest.name}`)
}

Type guard

function isBundle(b: unknown): b is NonNullable<ReturnType<TargetHandler["convert"]>> {
  return typeof b === "object" && b !== null
}

Try / catch

try {
  await convert({ to: targetName, source })
} catch (e) {
  if (e instanceof Error && e.message.includes("did not return a bundle")) {
    console.error(`Converter bug in '${targetName}': inspect its convert() handler; check the source plugin shape.`)
  } else throw e
}

Prevention

When it happens

Trigger: A custom or in-development target handler whose `convert` returns undefined/null (e.g. an early-return on an unhandled plugin shape, or a stub that returns nothing), then running convert against that target.

Common situations: Contributors adding a new target provider per the checklist whose convert implementation isn't finished; monkey-patching or wrapping a target handler in a script; a plugin manifest so malformed that the converter bails with a null return instead of throwing.

Related errors


AI-assisted analysis of EveryInc/compound-engineering-plugin@c9c10f8c75 (2026-08-31). Data as JSON: /api/errors/f0377a225e62db2a. Report an issue: GitHub.