affaan-m/ECC · error · Error

Missing rendered content for repair: ${operation.destination

Error message

Missing rendered content for repair: ${operation.destinationPath}

What it means

For a 'render-template' repair operation the installer asks getOperationTextContent for the rendered body. If it returns null (no `text`/`textContent`/inline body on the operation record), the repair cannot proceed because there is nothing to write. Like 162, the install-state is treated as attacker-controllable, so missing content is fatal rather than synthesized.

Source

Thrown at scripts/lib/install-lifecycle.js:611

function executeRepairOperation(repoRoot, operation, trustedRoot) {
  // Install-state is attacker-controllable; never write/delete outside the
  // adapter-derived trusted root, regardless of what the state file claims
  // (GHSA-hfpv-w6mp-5g95).
  if (operation.kind === 'copy-file') {
    const sourcePath = resolveOperationSourcePath(repoRoot, operation);
    if (!sourcePath || !fs.existsSync(sourcePath)) {
      throw new Error(`Missing source file for repair: ${sourcePath || operation.sourceRelativePath}`);
    }

    copyContainedFile(sourcePath, operation.destinationPath, trustedRoot, 'repair');
    return operation.destinationPath;
  }

  if (operation.kind === 'render-template') {
    const renderedContent = getOperationTextContent(operation);
    if (renderedContent === null) {
      throw new Error(`Missing rendered content for repair: ${operation.destinationPath}`);
    }

    writeContainedFile(operation.destinationPath, renderedContent, trustedRoot, 'repair');
    return operation.destinationPath;
  }

  if (operation.kind === 'merge-json') {
    const payload = getOperationJsonPayload(operation);
    if (payload === undefined) {
      throw new Error(`Missing merge payload for repair: ${operation.destinationPath}`);
    }

    const existingDestination = getContainedExistingPath(operation.destinationPath, trustedRoot, 'repair');
    const currentValue = existingDestination
      ? readJsonNoFollow(
        getManagedDestination(existingDestination, trustedRoot, 'repair').managedPath
      )
      : {};

View on GitHub (pinned to 01e15490f0)

Solutions

  1. Open the install-state file at record.installStatePath and inspect the offending operation entry — confirm it has a non-empty text/textContent body.
  2. If the entry is malformed, uninstall the affected target and re-install fresh so a correct state is generated.
  3. Upgrade the installer to a version whose operation schema matches the recorded operation.
  4. Restore the install-state file from backup if available.

Example fix

// before: operation = { kind: 'render-template', destinationPath: '...', /* no text */ }
// after: uninstall + reinstall to regenerate state
./install.sh --target claude --uninstall
./install.sh --target claude
Defensive patterns

Strategy: validation

Validate before calling

function hasRenderableContent(op) {
  if (op.kind !== 'render-template') return true;
  return getOperationTextContent(op) !== null;
}
// before repair: state.operations.every(hasRenderableContent)

Type guard

function isRenderableOperation(op) {
  return op.kind !== 'render-template' || getOperationTextContent(op) !== null;
}

Try / catch

try {
  await executeRepairOperation(repoRoot, op, trustedRoot);
} catch (err) {
  if (err.message.startsWith('Missing rendered content for repair')) {
    // reinstall the target to regenerate the operation with content
  } else throw err;
}

Prevention

When it happens

Trigger: Repair runs against an install-state whose render-template operation is missing its text content field, or whose content field was stripped/corrupted. Also after a version downgrade where the operation schema for template content changed.

Common situations: Install-state file edited by hand or partially overwritten; older install-state from a previous ECC version where the template body lived in a different field; a failed prior write truncated the state file.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/27abc046693ef31c. Report an issue: GitHub.