can1357/oh-my-pi · error

Malformed shipped docs index at ${embedPath}: payload withou

Error message

Malformed shipped docs index at ${embedPath}: payload without a newline separator. Rebuild the bundle.

What it means

The shipped docs index embed is stored as a payload line plus a newline separator. readShippedEmbed decodes it and throws if decoding fails, meaning the bundled embed file exists but is structurally broken (no newline separating payload from index). This indicates a corrupted or badly built bundle.

Source

Thrown at packages/coding-agent/src/internal-urls/docs-index.ts:106

/**
 * Prepacked npm package: the docs embed is written to `dist/docs-index.generated.txt`
 * during `gen:bundle` (compiled binaries inline it via `PI_DOCS_EMBED` instead).
 * SDK consumers importing `@oh-my-pi/pi-coding-agent/*` load TypeScript source, where
 * the build-time placeholder is empty, so this shipped file is their only reachable
 * corpus. Returns `null` when the file is absent (dev tree before a bundle build).
 */
function readShippedEmbed(): DocsIndex | null {
	const embedPath = path.resolve(import.meta.dir, "../../dist/docs-index.generated.txt");
	let raw: string;
	try {
		raw = readFileSync(embedPath, "utf8");
	} catch (err) {
		if (isEnoent(err)) return null;
		throw err;
	}
	const decoded = decodeDocsIndex(raw);
	if (decoded === null) {
		throw new Error(
			`Malformed shipped docs index at ${embedPath}: payload without a newline separator. Rebuild the bundle.`,
		);
	}
	return decoded;
}

/** Empty index for when no docs corpus is reachable — degrades `omp://` instead of throwing ENOENT at callers. */
function emptyIndex(): DocsIndex {
	logger.warn(
		"omp:// docs corpus unavailable: no build-time embed, on-disk docs/ directory, or shipped dist embed found",
	);
	return { filenames: [], getBody: () => Promise.resolve(undefined) };
}

let index: DocsIndex | undefined;
function getIndex(): DocsIndex {
	if (index !== undefined) return index;
	// Populated embed in compiled binaries / npm bundle entrypoint. A non-empty

View on GitHub (pinned to 9690622007)

Solutions

  1. Reinstall/rebuild the package so the shipped docs embed is regenerated
  2. Verify embedPath points at the embed from the same version as the code
  3. As a fallback, rely on non-embedded docs loading (disk/network) if available

Example fix

// before (corrupted embed)
# bundle/docs-index.embed  (single truncated line)
// after
bun run build  # regenerate the bundle and its docs embed
Defensive patterns

Strategy: fallback

Validate before calling

const raw = await Bun.file(embedPath).text()
if (raw.length > 0 && !raw.includes('\n')) throw new Error(`shipped docs embed corrupt at ${embedPath}`)

Try / catch

try {
  index = await readShippedEmbed()
} catch (err) {
  if (String(err).includes('Malformed shipped docs index')) {
    logger.warn('shipped docs embed corrupt; docs disabled', { embedPath })
    return emptyIndex
  }
  throw err
}

Prevention

When it happens

Trigger: Loading the docs index (getIndex) from the shipped embed file when its content has no newline separator — i.e. a truncated or incorrectly assembled embed at embedPath.

Common situations: Interrupted install/bundle step left a partial embed file; hand-edited or corrupted file in the package; version mismatch where a new reader reads an old embed format.

Understand the failure class

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/bc81bdad6149d4f5. Report an issue: GitHub.