{"record":{"id":"dc02b0ce7bf9f99e","repo":"siyuan-note/siyuan","slug":"invalid-image-operation-state","errorCode":null,"errorMessage":"invalid image operation state","messagePattern":"invalid image operation state","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/mcp/tools/image.go","lineNumber":290,"sourceCode":"\tif record.AssetPath != \"\" && !imageOperationAssetExists(record.DocumentID, record.AssetPath) {\n\t\tremoveImageOperationRecord(key)\n\t\treturn CallToolResult{}, false\n\t}\n\treturn record.Result, true\n}\n\nfunc saveImageOperationRecord(key string, meta imageOperationMeta, state string, result CallToolResult) error {\n\tif !validImageOperationKey(key) {\n\t\treturn errors.New(\"invalid image operation key\")\n\t}\n\tassetPath := meta.AssetPath\n\tif state == imageOperationStateCompleted {\n\t\tif resultPath := imageResultAssetPath(result); resultPath != \"\" {\n\t\t\tassetPath = resultPath\n\t\t}\n\t}\n\tif state != imageOperationStateRunning && state != imageOperationStateCompleted {\n\t\treturn errors.New(\"invalid image operation state\")\n\t}\n\trecord := imageOperationRecord{\n\t\tVersion: 1, CreatedAt: time.Now().UnixMilli(), State: state, Action: meta.Action, DocumentID: meta.DocumentID,\n\t\tAssetPath: assetPath, Result: result,\n\t}\n\tdata, err := json.Marshal(record)\n\tif err != nil {\n\t\treturn err\n\t}\n\tpath := imageOperationRecordPath(key)\n\tif err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {\n\t\treturn err\n\t}\n\treturn filelock.WriteFile(path, data)\n}\n\nfunc removeImageOperationRecord(key string) {\n\tif !validImageOperationKey(key) {","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/mcp/tools/image.go#L272-L308","documentation":"saveImageOperationRecord validates the state argument after computing the asset path: only imageOperationStateRunning and imageOperationStateCompleted are accepted. This error is returned when a caller tries to persist an operation record with a state value outside that enumerated set, so unknown or future state strings cannot corrupt the persisted operation history.","triggerScenarios":"runImageOperation (or the test TestRunImageOperationBlocksUnknownPendingOperation) passes a state string other than 'running' or 'completed' — e.g. a typo like 'runnning', 'failed' (handled via a different path), or an empty state variable.","commonSituations":"A code change introduces a new state (e.g. 'cancelled') without adding it to this validation; a refactor renames the constants at one call site; a caller passes a state derived from an unvalidated external input.","solutions":["Pass only imageOperationStateRunning or imageOperationStateCompleted to saveImageOperationRecord","If a new lifecycle state is needed, add it to this validation and to the record schema (bump record Version) deliberately","Check the call site for a typo or swapped constant when this error appears during development","Route failure outcomes through the error/result path instead of inventing a 'failed' state record"],"exampleFix":"// before\nsaveImageOperationRecord(key, meta, \"failed\", errResult)\n// after\nsaveImageOperationRecord(key, meta, imageOperationStateCompleted, errResult) // failures are recorded as completed with an error result","handlingStrategy":"type-guard","validationCode":"const VALID_STATES = ['running', 'completed'];\nif (!VALID_STATES.includes(state)) throw new Error(`unsupported operation state: ${state}`);","typeGuard":"const isImageOpState = (s) => s === 'running' || s === 'completed';","tryCatchPattern":null,"preventionTips":["Always use the exported state constants, not raw strings","Centralize state transitions in one helper that validates before saving","When adding a new state, update the validation and the record schema together"],"tags":["mcp","image","enum","state-management"],"backgroundTag":"invalid-enum-value","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}