Skip to content

fix: skip empty node name in local snapshot info after pause finalization#329

Open
Mesut Oezdil (mesutoezdil) wants to merge 5 commits into
agent-substrate:mainfrom
mesutoezdil:fix/pause-empty-nodename
Open

fix: skip empty node name in local snapshot info after pause finalization#329
Mesut Oezdil (mesutoezdil) wants to merge 5 commits into
agent-substrate:mainfrom
mesutoezdil:fix/pause-empty-nodename

Conversation

@mesutoezdil

@mesutoezdil Mesut Oezdil (mesutoezdil) commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

When the worker pod is gone from the DB during pause finalization, nodeName stays empty.
The code still wrote NodeVmsWithLocalSnapshots: []string{""}, so on the next ResumeActor the scheduler looked for a worker with node name "", found none, and returned "no free workers available" permanently.
Fix: only set NodeVmsWithLocalSnapshots when nodeName is non-empty.

@dberkov

Copy link
Copy Markdown
Collaborator

Mesut Oezdil (@mesutoezdil) - could you please explain how you was able to reproduce the issue, since the proposed fix will not work. The root cause of the issue is somewhere else.

@mesutoezdil

Copy link
Copy Markdown
Contributor Author

Mesut Oezdil (Mesut Oezdil (@mesutoezdil)) - could you please explain how you was able to reproduce the issue, since the proposed fix will not work. The root cause of the issue is somewhere else.

here are the reproduction steps, i wrote 2 unit tests:

T1 // (TestFinalizePausedStep_WorkerGone): worker pod is gone from db before FinalizePausedStep runs. GetWorker returns ErrNotFound.
and
T2 // (TestFindFreeWorker_EmptyNodeRestriction): shows why it gets stuck, and old code wrote []string{""} into NodeVmsWithLocalSnapshots. findFreeWorker then looks for a worker with NodeName == "", finds none, returns nil forever.

Screenshot 2026-06-27 at 07 07 43

see your point about root cause. Even with this fix, resume could pick a wrong node and snapshot restore fails.
and I saw your TODO on line 215, should we move actor to CRASHED when nodeName is empty instead?

@dberkov

Copy link
Copy Markdown
Collaborator

Zoe Zhao (@zoez7) is working on a PR introducing the CRASHED state. Could you please wait for her PR to be submitted and after it make a change to move the actor to this stage in case of this condition.

@mesutoezdil
Mesut Oezdil (mesutoezdil) force-pushed the fix/pause-empty-nodename branch 2 times, most recently from f14d87d to 907531c Compare July 14, 2026 18:59
Without a node name the local snapshot can never be resumed since
findFreeWorker would search for a worker on an unknown node forever.
Move the actor to CRASHED instead of leaving it stuck in PAUSED.

CRASHED is now a terminal state for the workflow, mirroring PAUSED.
// so the actor can never be resumed (findFreeWorker would search for a
// worker on an unknown node forever). Crash it instead of leaving it
// stuck in PAUSED.
slog.Warn("Node name not found during finalize pause, crashing actor", "actor", input.ActorName)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use slog.ErrorCtx instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thx zoe, done

SnapshotPrefix: latestActor.InProgressSnapshot,
}
if nodeName != "" {
localInfo.NodeVmsWithLocalSnapshots = []string{nodeName}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resume from "SnapshotType_SNAPSHOT_TYPE_LOCAL" supposed to land on machine where files are stored locally, otherwise resume will fail.

we need to find a root cause of the issue that node is empty. This is a bug/exception

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should be a separete issue i think,i dont solve it in this pr

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 Dmitry Berkovich (@dberkov) I think you described a different bug than the one this PR is solving

I think this PR solves a idempotency problem that we don't handle today.

  1. CallAteletPauseStep succeeded, but we havn't called FinalizePausedStep yet
  2. ate-apiserver restarts.
  3. WorkerPod gets deleted.
  4. Retry PauseActor.
    Now we don't know which node the snapshot is on, we can only crash the actor.

I think we should check this PR in as a temporary fix, but we also need to add node name as a field in the actor API, so Pause can be idempotent.

localInfo := &ateapipb.LocalSnapshotInfo{
SnapshotPrefix: latestActor.InProgressSnapshot,
}
if nodeName != "" {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the nodeName != "" no more relevant, since it is already validated above

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants