siyuan-note/siyuan · error
invalid image operation state
Error message
invalid image operation state
What it means
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.
Source
Thrown at kernel/mcp/tools/image.go:290
if record.AssetPath != "" && !imageOperationAssetExists(record.DocumentID, record.AssetPath) {
removeImageOperationRecord(key)
return CallToolResult{}, false
}
return record.Result, true
}
func saveImageOperationRecord(key string, meta imageOperationMeta, state string, result CallToolResult) error {
if !validImageOperationKey(key) {
return errors.New("invalid image operation key")
}
assetPath := meta.AssetPath
if state == imageOperationStateCompleted {
if resultPath := imageResultAssetPath(result); resultPath != "" {
assetPath = resultPath
}
}
if state != imageOperationStateRunning && state != imageOperationStateCompleted {
return errors.New("invalid image operation state")
}
record := imageOperationRecord{
Version: 1, CreatedAt: time.Now().UnixMilli(), State: state, Action: meta.Action, DocumentID: meta.DocumentID,
AssetPath: assetPath, Result: result,
}
data, err := json.Marshal(record)
if err != nil {
return err
}
path := imageOperationRecordPath(key)
if err = os.MkdirAll(filepath.Dir(path), 0755); err != nil {
return err
}
return filelock.WriteFile(path, data)
}
func removeImageOperationRecord(key string) {
if !validImageOperationKey(key) {View on GitHub (pinned to 8641553a1f)
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
Example fix
// before saveImageOperationRecord(key, meta, "failed", errResult) // after saveImageOperationRecord(key, meta, imageOperationStateCompleted, errResult) // failures are recorded as completed with an error result
Defensive patterns
Strategy: type-guard
Validate before calling
const VALID_STATES = ['running', 'completed'];
if (!VALID_STATES.includes(state)) throw new Error(`unsupported operation state: ${state}`); Type guard
const isImageOpState = (s) => s === 'running' || s === 'completed';
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- invalid image operation key
- image operation failed
- unsupported or invalid image:
- decode image failed:
- encode image failed:
AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11).
Data as JSON: /api/errors/dc02b0ce7bf9f99e.
Report an issue: GitHub.