{"record":{"id":"0ec9abdb9590d756","repo":"Fission-AI/OpenSpec","slug":"change-changename-has-no-proposal-md-yet-run","errorCode":null,"errorMessage":"Change \"${changeName}\" has no proposal.md yet. Run \"openspec status --change ${changeName}\" to see which artifact comes next.","messagePattern":"Change \"(.+?)\" has no proposal\\.md yet\\. Run \"openspec status --change (.+?)\" to see which artifact comes next\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/commands/change.ts","lineNumber":103,"sourceCode":"    if (!isChangeDirectoryName(changesPath, changeDir)) {\n      throw new Error(`Change \"${changeName}\" not found at ${proposalPath}`);\n    }\n\n    try {\n      await fs.access(proposalPath);\n    } catch {\n      // A change can exist without a proposal: `openspec new change` scaffolds\n      // only .openspec.yaml, and a custom schema need not define a proposal\n      // artifact. Say which of the two cases this is instead of reporting a\n      // change that does exist as missing. A stray file under changes/ is not a\n      // change, and naming it one would point the user at a `status --change`\n      // call that cannot work.\n      const isChangeDirectory = await fs\n        .stat(changeDir)\n        .then((stats) => stats.isDirectory())\n        .catch(() => false);\n      if (isChangeDirectory) {\n        throw new Error(\n          `Change \"${changeName}\" has no proposal.md yet. ` +\n            `Run \"openspec status --change ${changeName}\" to see which artifact comes next.`\n        );\n      }\n      throw new Error(`Change \"${changeName}\" not found at ${proposalPath}`);\n    }\n    FileSystemUtils.assertPathWithin(path.dirname(proposalPath), proposalPath);\n\n    if (options?.json) {\n      FileSystemUtils.assertPathWithin(changeDir, proposalPath);\n      const jsonOutput = await this.converter.convertChangeToJson(proposalPath);\n\n      if (options.requirementsOnly) {\n        console.error('Flag --requirements-only is deprecated; use --deltas-only instead.');\n      }\n\n      const parsed: Change = JSON.parse(jsonOutput);\n      FileSystemUtils.assertPathWithin(changeDir, proposalPath);","sourceCodeStart":85,"sourceCodeEnd":121,"githubUrl":"https://github.com/Fission-AI/OpenSpec/blob/6926ccb18afa4ff621112813e9968334576ee11a/src/commands/change.ts#L85-L121","documentation":"Error \"Change \"${changeName}\" has no proposal.md yet. Run \"openspec status --change ${changeName}\" to see which artifact comes next.\" thrown in Fission-AI/OpenSpec.","triggerScenarios":"Thrown at src/commands/change.ts:103 when the library encounters an invalid state.","commonSituations":"See trigger scenarios.","solutions":[],"exampleFix":null,"handlingStrategy":null,"validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":[],"tags":[],"backgroundTag":null,"analyzedSha":"6926ccb18afa4ff621112813e9968334576ee11a","analyzedAt":"2026-08-25T12:29:45.729Z","schemaVersion":2},"datasetVersion":"2026-08-25T16:17:27.014Z"}