Re-run the failed jobs of a completed workflow run
POST/api/workflow-runs/{run_id}/rerun-failed-jobs
rerunFailedWorkflowRunJobs
GHA "re-run failed jobs": creates a fresh attempt of a finished run that CARRIES every succeeded job whose whole `needs:` closure also succeeded — carried jobs are born `succeeded` with the original outputs and report `carried_from` — and re-executes every other job. Artifact list/download of the new attempt inherit what earlier attempts uploaded. Same authorization, quota and concurrency decisions as `/rerun`. 409 while the source run is still active, and when it has no failed or cancelled job; 400 when its workflow is no longer active.
Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.
curl
curl -X POST 'https://neosource.dev/api/workflow-runs/RUN_ID/rerun-failed-jobs'fetch
fetch("https://neosource.dev/api/workflow-runs/RUN_ID/rerun-failed-jobs", {
method: "POST",
});Path parameters
run_idrequired
Responses
201New attempt enqueued
application/json
403Forbidden — one of: forbidden, needs_scope
application/json
Standard errors
Bodies documented once for the whole API — see standard errors.
- 400Bad Request — one of: invalid_input
- 404Not Found — one of: not_found
- 409Conflict — one of: already_exists, conflict, github_sync_active
- 429Rate limited — retry after the `Retry-After` header
- 500Internal server error
- 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
- 504Gateway timeout — the request exceeded the server's handling budget
Schemas
Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.
WorkflowRunTestFailure
One failing test out of the run's `JUnit` report.
messageThe failure/error message attribute, when present.
namerequiredTest identity: `classname::name` when the report carries a classname, else the bare testcase name.
ResolvedToolchain
What the catalog answered, and what a re-run re-materializes.
artifactrequiredtoolrequiredCanonical tool name (aliases resolve to it), or the raw name for a passthrough installable.
variantDistribution/vendor where the tool has one (`temurin`, `zulu`, …).
versionrequiredThe concrete version. **Open vocabulary, deliberately `String`** — the set of version strings is unbounded by construction, so this is the documented exception to the closed-set-DTO-enum rule.
NixStorePath
An absolute, well-formed store path — `<root>/<hash>-<name>` for SOME valid [`NixStoreRoot`] — validated on construction AND on deserialize. **The grammar is a property of the VALUE, not a step some caller remembers.** `ToolArtifact::StorePath` is deserialized straight out of `workflow_runs.toolchain_manifest` jsonb and is the agent's whole authorization surface (`ToolchainManifest::has_store_path`), so a raw `String` there would let `/etc/passwd` answer "recorded" the moment it byte-matched a recorded entry. Validating in `Deserialize` too is the half that matters: an invariant that holds only for freshly-built values is not an invariant, and every value on this path arrives from a database. Deliberately ROOT-INDEPENDENT: whether a path is under the root *this* process serves is [`store_path_leaf`]'s question, and that root is env-configurable. This type answers the other one — is it shaped like a store path at all. Which means the grammar alone is NOT the authorization answer, and the doc must not be read as claiming it is: `/etc` is a root [`NixStoreRoot`] admits, so `/etc/<hash>-passwd` is a well-formed value of this type. Pinning a RECORDED artifact to the real store is [`crate::model::toolchain::StorePathArtifact::new`]'s clause, one layer up, where the recording happens.