{"record":{"id":"642776f14ead3dc5","repo":"BloopAI/vibe-kanban","slug":"executor-action-is-not-a-valid-executoraction-json","errorCode":null,"errorMessage":"Executor action is not a valid ExecutorAction JSON object","messagePattern":"Executor action is not a valid ExecutorAction JSON object","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/db/src/models/execution_process.rs","lineNumber":461,"sourceCode":"        sqlx::query!(\n            r#\"UPDATE execution_processes\n               SET status = $1, exit_code = $2, completed_at = $3\n               WHERE id = $4\"#,\n            status,\n            exit_code,\n            completed_at,\n            id\n        )\n        .execute(pool)\n        .await?;\n\n        Ok(())\n    }\n\n    pub fn executor_action(&self) -> Result<&ExecutorAction, anyhow::Error> {\n        match &self.executor_action.0 {\n            ExecutorActionField::ExecutorAction(action) => Ok(action),\n            ExecutorActionField::Other(_) => Err(anyhow::anyhow!(\n                \"Executor action is not a valid ExecutorAction JSON object\"\n            )),\n        }\n    }\n\n    /// Soft-drop processes at and after the specified boundary (inclusive)\n    pub async fn drop_at_and_after(\n        pool: &SqlitePool,\n        session_id: Uuid,\n        boundary_process_id: Uuid,\n    ) -> Result<i64, sqlx::Error> {\n        let result = sqlx::query!(\n            r#\"UPDATE execution_processes\n               SET dropped = TRUE\n             WHERE session_id = $1\n               AND created_at >= (SELECT created_at FROM execution_processes WHERE id = $2)\n               AND dropped = FALSE\"#,\n            session_id,","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/BloopAI/vibe-kanban/blob/4deb7eca8f381f7cbc1f9d15515a9ab8f8009053/crates/db/src/models/execution_process.rs#L443-L479","documentation":"An ExecutionProcess row stores its executor action as JSON that is expected to deserialize into an ExecutorAction. This accessor returns Err when the stored JSON is the 'Other' variant — i.e. the payload is valid JSON but not a recognized ExecutorAction shape (unknown/legacy executor payload, or an externally-written row).","triggerScenarios":"Calling execution_process.executor_action() on a row whose executor_action JSON column parsed as ExecutorActionField::Other instead of ExecutorActionField::ExecutorAction.","commonSituations":"Database rows written by an older version of the app before a ts-rs/schema change, manual DB edits or migrations inserting raw JSON, or rows created by a different executor plugin not known to the current enum.","solutions":["Inspect the row's executor_action JSON and re-write it as a valid ExecutorAction object matching the current schema.","Check whether the row predates an executor schema change; re-run the task/process so a fresh row is created with the current format.","If the payload is intentionally unsupported, handle the Err case and skip/derive actions from alternative columns instead of unwrapping.","Add a DB migration or backfill script that converts legacy 'Other' payloads to the current ExecutorAction format."],"exampleFix":"// before\nlet action = process.executor_action()?;\n// after\nlet action = match process.executor_action() {\n    Ok(a) => a,\n    Err(_) => { tracing::warn!(id = %process.id, \"unsupported executor action payload\"); continue; }\n};","handlingStrategy":"type-guard","validationCode":"fn is_supported_executor_action(json: &serde_json::Value) -> bool {\n    json.get(\"type\").and_then(|t| t.as_str())\n        .map(|t| matches!(t, \"coding-agent\" | \"script\"))\n        .unwrap_or(false)\n}","typeGuard":"fn as_executor_action(\n    process: &ExecutionProcess,\n) -> Option<&ExecutorAction> {\n    process.executor_action().ok()\n}","tryCatchPattern":"let action = match process.executor_action() {\n    Ok(a) => a,\n    Err(e) => {\n        tracing::warn!(process_id = %process.id, error = %e, \"skipping legacy executor payload\");\n        return Ok(None);\n    }\n};","preventionTips":["Handle the Err branch instead of unwrapping executor_action().","After executor schema changes, add migrations/backfills for old rows.","Audit rows created outside the app (manual edits, other tools).","Pin the ts-rs generated types so payload shapes stay in sync between frontend and backend."],"tags":["database","serialization","schema-mismatch"],"backgroundTag":"schema-validation-failed","analyzedSha":"4deb7eca8f381f7cbc1f9d15515a9ab8f8009053","analyzedAt":"2026-08-29T09:24:13.446Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}