pbakaus/impeccable · error

preflight returned no scaffold metadata

Error message

preflight returned no scaffold metadata

What it means

runGenerationPreflight() (skill/scripts/live/generation-preflight.mjs) spawns `node live-insert.mjs|live-wrap.mjs --id ... --defer-source-write ...` with a 15s timeout to scaffold a generate event before the agent takes over. The helper's stdout is expected to end with a JSON metadata line, which is then JSON.parsed and its sourceFile/file cached by target signature. This error means the subprocess exited 0 but produced no non-empty stdout line at all — the metadata line is simply absent.

Solutions

  1. Re-run the helper manually with the same arguments (visible in server logs) and inspect stdout — no trailing JSON line confirms the mismatch
  2. Make scriptsDir contain the same skill version as the server: refresh/reinstall the skill or rebuild in the repo
  3. If the helper prints a not-found/quiet result, fix the locator (element id/classes/tag) so the scaffold actually resolves
  4. Keep server and helper scripts updated together — the preflight contract (exit 0 + last-line JSON) is version-coupled
Defensive patterns

Strategy: validation

Validate before calling

import fs from 'node:fs';
import path from 'node:path';

// Before relying on preflight, confirm the helper this server version expects
// is the one actually present in scriptsDir.
for (const helper of ['live-insert.mjs', 'live-wrap.mjs']) {
  const p = path.join(scriptsDir, helper);
  if (!fs.existsSync(p)) throw new Error(`helper missing: ${p}`);
}

Try / catch

const result = await runGenerationPreflight(event, { cwd, scriptsDir });
if (!result.ok && result.reason?.includes('preflight returned no scaffold metadata')) {
  // Version/install mismatch: run the printed helper args manually,
  // then refresh the skill so server and helpers share one version.
  logRecoveryHint(result.reason);
}

Prevention

When it happens

Trigger: An older live-insert.mjs/live-wrap.mjs in scriptsDir that doesn't implement the trailing metadata line (version mismatch with the server); a quiet not-found code path that exits successfully without printing; output swallowed by a wrapper; stdout redirected inside the helper.

Common situations: Partial skill updates leaving new live-server.mjs paired with stale helper scripts; custom installs where scriptsDir mixes versions; helper behavior changing across releases while the cached signature path expects the new format.

Related errors


AI-assisted analysis of pbakaus/impeccable@f88b2837a7 (2026-08-18). Data as JSON: /api/errors/6902ef1e441bb932. Report an issue: GitHub.

Appendix: source

Thrown at skill/scripts/live/generation-preflight.mjs:92

  scriptsDir,
  execFileImpl = execFileAsync,
  timeoutMs = PREFLIGHT_TIMEOUT_MS,
  cache = sourceResolutionCache,
} = {}) {
  const command = buildGenerationPreflight(event, scriptsDir, { cache });
  if (!command) {
    return { ok: false, skipped: true, reason: 'insufficient_locator' };
  }

  const startedAt = performance.now();
  try {
    const { stdout } = await execFileImpl(process.execPath, command.args, {
      cwd,
      encoding: 'utf-8',
      timeout: timeoutMs,
    });
    const line = String(stdout).trim().split('\n').filter(Boolean).pop();
    if (!line) throw new Error('preflight returned no scaffold metadata');
    const scaffold = JSON.parse(line);
    // Cache the resolved SOURCE file (route source, not the svelte manifest) so
    // the next generate on this target skips the tree search.
    const resolvedSource = scaffold.sourceFile || scaffold.file;
    if (cache && command.signature && typeof resolvedSource === 'string') {
      cache.set(command.signature, resolvedSource);
    }
    return {
      ok: true,
      mode: command.mode,
      durationMs: performance.now() - startedAt,
      scaffold,
    };
  } catch (error) {
    // Evict a stale/failed resolution so the next attempt does a full search
    // (the element may have moved out of the previously cached file).
    if (cache && command.signature) cache.delete(command.signature);
    return {

View on GitHub (pinned to f88b2837a7)