BloopAI/vibe-kanban · error
Executor action is not a valid ExecutorAction JSON object
Error message
Executor action is not a valid ExecutorAction JSON object
What it means
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).
Source
Thrown at crates/db/src/models/execution_process.rs:461
sqlx::query!(
r#"UPDATE execution_processes
SET status = $1, exit_code = $2, completed_at = $3
WHERE id = $4"#,
status,
exit_code,
completed_at,
id
)
.execute(pool)
.await?;
Ok(())
}
pub fn executor_action(&self) -> Result<&ExecutorAction, anyhow::Error> {
match &self.executor_action.0 {
ExecutorActionField::ExecutorAction(action) => Ok(action),
ExecutorActionField::Other(_) => Err(anyhow::anyhow!(
"Executor action is not a valid ExecutorAction JSON object"
)),
}
}
/// Soft-drop processes at and after the specified boundary (inclusive)
pub async fn drop_at_and_after(
pool: &SqlitePool,
session_id: Uuid,
boundary_process_id: Uuid,
) -> Result<i64, sqlx::Error> {
let result = sqlx::query!(
r#"UPDATE execution_processes
SET dropped = TRUE
WHERE session_id = $1
AND created_at >= (SELECT created_at FROM execution_processes WHERE id = $2)
AND dropped = FALSE"#,
session_id,View on GitHub (pinned to 4deb7eca8f)
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.
Example fix
// before
let action = process.executor_action()?;
// after
let action = match process.executor_action() {
Ok(a) => a,
Err(_) => { tracing::warn!(id = %process.id, "unsupported executor action payload"); continue; }
}; Defensive patterns
Strategy: type-guard
Validate before calling
fn is_supported_executor_action(json: &serde_json::Value) -> bool {
json.get("type").and_then(|t| t.as_str())
.map(|t| matches!(t, "coding-agent" | "script"))
.unwrap_or(false)
} Type guard
fn as_executor_action(
process: &ExecutionProcess,
) -> Option<&ExecutorAction> {
process.executor_action().ok()
} Try / catch
let action = match process.executor_action() {
Ok(a) => a,
Err(e) => {
tracing::warn!(process_id = %process.id, error = %e, "skipping legacy executor payload");
return Ok(None);
}
}; Prevention
- 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.
When it happens
Trigger: Calling execution_process.executor_action() on a row whose executor_action JSON column parsed as ExecutorActionField::Other instead of ExecutorActionField::ExecutorAction.
Common situations: 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.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- Migration failed: {}
- Migration DB pool error: {}
- Failed to copy database file
- Execution process serialization should not fail
- Workspace serialization should not fail
AI-assisted analysis of BloopAI/vibe-kanban@4deb7eca8f (2026-08-29).
Data as JSON: /api/errors/642776f14ead3dc5.
Report an issue: GitHub.