Fission-AI/OpenSpec · error · Error

The staged fork of '${source}' is not a valid schema (the so

Error message

The staged fork of '${source}' is not a valid schema (the source may have changed during copy); aborted, '${destinationName}' was not modified.

What it means

Error "The staged fork of '${source}' is not a valid schema (the source may have changed during copy); aborted, '${destinationName}' was not modified." thrown in Fission-AI/OpenSpec.

Source

Thrown at src/commands/schema.ts:807

          // Update name in the staged schema.yaml via yaml's Document API
          // instead of re-serializing the parsed object, so block scalars,
          // comments, and key order in the source schema.yaml survive the fork.
          const stagedSchemaPath = path.join(stagingDir, 'schema.yaml');
          const schemaContent = fs.readFileSync(stagedSchemaPath, 'utf-8');
          const doc = parseDocument(schemaContent);
          doc.set('name', destinationName);
          fs.writeFileSync(stagedSchemaPath, doc.toString());

          // Authoritative gate: validate the COMPLETED staged schema — the exact
          // bytes we are about to install — not just the source at the pre-check.
          // The source files copyDirRecursive reads can change mid-copy, so a
          // source that was valid up front can still produce an invalid staged
          // fork. Validating here, before ANY destructive step, guarantees we
          // never install an invalid fork or delete a valid destination for one.
          try {
            parseSchema(fs.readFileSync(stagedSchemaPath, 'utf-8'));
          } catch (validationError) {
            throw new Error(
              `The staged fork of '${source}' is not a valid schema (the source may have changed during copy); ` +
                `aborted, '${destinationName}' was not modified.`,
              { cause: validationError }
            );
          }

          // Swap the staged fork into place. When a destination already exists,
          // move it aside to a sibling backup FIRST, then install the staged
          // fork; only once the install succeeds is the backup discarded. If the
          // install rename itself fails (e.g. a Windows lock), the backup is
          // moved back so the user's original destination is never lost.
          if (destinationExists) {
            if (spinner) spinner.text = `Replacing existing schema '${destinationName}'...`;

            // Revalidate immediately before the destructive move: if the
            // destination changed on disk while we were staging (or was removed),
            // its fingerprint no longer matches what the user authorized. Abort
            // WITHOUT touching it, so the concurrent changes are preserved. The

View on GitHub (pinned to 6926ccb18a)

When it happens

Trigger: Thrown at src/commands/schema.ts:807 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of Fission-AI/OpenSpec@6926ccb18a (2026-08-25). Data as JSON: /api/errors/c2c8be27628f5630. Report an issue: GitHub.