kestra-io/kestra · error · IllegalStateException
Cannot repair migration script [<scriptId>] because it has n
Error message
Cannot repair migration script [<scriptId>] because it has not been applied.
What it means
Thrown by repairChecksum() when historyStore.isApplied(scriptId) returns false — the script was never executed against the backend, so there is no stored checksum row to update. Repair is only meaningful for scripts already recorded in migration history. This is an IllegalStateException (not argument) signalling the requested operation is invalid for the current backend state.
Source
Thrown at core/src/main/java/io/kestra/core/migration/MigrationRunner.java:151
public void repairChecksum(final String scriptId) throws MigrationLockedException, Exception {
if (!lock.tryAcquire()) {
throw new MigrationLockedException();
}
try {
historyStore.bootstrapIfNeeded();
MigrationScript script = scripts.stream()
.filter(candidate -> candidate.scriptId().equals(scriptId))
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Unknown migration script [" + scriptId + "]."));
if (script.checksum() == null) {
throw new IllegalArgumentException("Migration script [" + scriptId + "] has no checksum to repair.");
}
if (!historyStore.isApplied(scriptId)) {
throw new IllegalStateException("Cannot repair migration script [" + scriptId + "] because it has not been applied.");
}
historyStore.updateChecksum(script);
log.info("Migration checksum repaired for script [{}].", scriptId);
} finally {
lock.release();
}
}
/**
* Returns all scripts that have not yet been applied, sorted by {@code scriptId}.
* Used by EE to detect pending scripts before deciding whether to run or fail.
*
* <p>
* This method does <strong>not</strong> acquire the migration lock. It is intended as a
* read-only startup check on a single node (EE {@code auto=false} path) to decide whether to
* throw {@link MigrationPendingException}. In multi-node deployments, callers should be aware
* that another node may concurrently apply migrations between this call and any subsequent action.View on GitHub (pinned to 823fada927)
Solutions
- Run 'kestra migrate' to apply pending scripts first.
- After migration completes, re-run 'kestra migrate repair <scriptId>' if a checksum drift still exists.
- If the script should already be applied, verify the history table is not corrupt or truncated.
Example fix
// before $ kestra migrate repair 0_009_xyz // IllegalStateException: not applied // after $ kestra migrate // apply first $ kestra migrate repair 0_009_xyz
Defensive patterns
Strategy: validation
Validate before calling
if (!historyStore.isApplied(scriptId)) {
log.warn("Script {} not applied yet; run migrations before repair.", scriptId);
return;
} Try / catch
try {
migrationRunner.repairChecksum(scriptId);
} catch (IllegalStateException e) {
log.warn("Cannot repair {}: {}", scriptId, e.getMessage());
// run 'kestra migrate' first, then retry
} Prevention
- Apply all pending migrations before repairing checksums.
- Verify history-store state before invoking repair.
When it happens
Trigger: Calling repair on a pending (not-yet-applied) migration script; calling repair before any migrations have run on a fresh instance; the history store bootstrap recorded the script as absent.
Common situations: New script added that has not yet been executed; operator assumes a script ran but it was skipped; fresh database where history is empty.
Related errors
- Migration script [<scriptId>] has no checksum to repair.
- onboarding.tour.errors.no_execution_to_replay
- Migration lock is held by another process. Another instance
- Cannot import file of type <type>
- QueryFilter must be either a leaf (field + operation) or a n
AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14).
Data as JSON: /api/errors/33f77b507a342dd2.
Report an issue: GitHub.