Skip to content

Log EMR cluster StateChangeReason on transient mode failure#100

Merged
Oguzhan Unlu (oguzhanunlu) merged 2 commits into
developfrom
transient-reason
Jun 8, 2026
Merged

Log EMR cluster StateChangeReason on transient mode failure#100
Oguzhan Unlu (oguzhanunlu) merged 2 commits into
developfrom
transient-reason

Conversation

@oguzhanunlu

Copy link
Copy Markdown
Member

In transient mode (run-transient) the cluster is launched with its steps embedded and the runner only waits for it to terminate. When the cluster terminates with errors — provisioning, quota, IAM or networking errors, or a bootstrap failure — the ClusterTerminatedWaiter returns a generic "transitioned to Failure" error and the underlying StateChangeReason was never surfaced, leaving transient runs blind to why the cluster died.

On waiter failure, re-describe the cluster and surface Cluster.Status.StateChangeReason Code and Message both in the logs and in the returned error, mirroring the persistent path added in #98.

ref: https://snplow.atlassian.net/browse/PDP-2682

In transient mode (run-transient) the cluster is launched with its steps
embedded and the runner only waits for it to terminate. When the cluster
terminates with errors — provisioning, quota, IAM or networking errors, or
a bootstrap failure — the ClusterTerminatedWaiter returns a generic
"transitioned to Failure" error and the underlying StateChangeReason was
never surfaced, leaving transient runs blind to why the cluster died.

On waiter failure, re-describe the cluster and surface
Cluster.Status.StateChangeReason Code and Message both in the logs and in
the returned error, mirroring the persistent path added in #98.
@istreeter

Copy link
Copy Markdown
Contributor

The following is unashamedly copy and pasted out of a conversation with Claude. See if you think these are legitimate complaints:

One thing worth considering before we close this off: when a step fails (rather than the cluster failing to provision), EMR terminates the cluster with TERMINATED_WITH_ERRORS. The waiter treats that as a failure and returns an error, so the new StateChangeReason logging will fire — you'll see something like code=STEP_FAILURE in the logs, which is better than nothing. But because we exit immediately at that point, GetFailedStepIDs() and displayFailedStepsLogs() are never reached. So in transient mode, --log-failed-steps effectively does nothing — the flag is accepted but the step-level log output is silently skipped. Worth deciding whether that's in scope here or a separate follow-up.

A couple of smaller things:

  • If the re-describe call itself fails (derr != nil), the error is silently dropped and we fall through with the original generic waiter message. A log.Warnf("could not re-describe cluster to get StateChangeReason: %v", derr) would at least tell you why you're seeing the generic message rather than leaving you wondering whether the re-describe was even attempted.

  • The nesting inside the ifif desc, derr := ...; derr == nil && desc.Cluster != nil && desc.Cluster.Status != nil — is a bit dense for something that's already inside an error branch. Given that clusterStateChangeReason is already extracted into its own function, pulling the re-describe logic into a small helper (something like fetchStateChangeReason(svc, clusterID)) would make it easier to test and read. Not a blocker.

  • The bootstrap-failure retry gap is still present (transient mode won't retry on bootstrap failures the way up does) — but that's probably a separate ticket.

@oguzhanunlu

Copy link
Copy Markdown
Member Author

So in transient mode, --log-failed-steps effectively does nothing

I checked this concern by reproducing a run-transient execution with --log-failed-steps flag. I can see logs of the failed step, hence the concern isn't valid.

Screenshot 2026-06-08 at 13 40 31

See the transient cluster's events history for a full picture. The cluster provisions fine and a step fails, resulting in TERMINATED, not TERMINATED_WITH_ERRORS (claude's claim).

Screenshot 2026-06-08 at 13 38 42

I pushed a new commit to address the smaller things listed except retry. I think that's a separate ticket.

@istreeter

Copy link
Copy Markdown
Contributor

OK thanks for checking. It seems Claude was wrong on this one. The logs you are shared are exactly what we need.

@oguzhanunlu Oguzhan Unlu (oguzhanunlu) merged commit 96bde0d into develop Jun 8, 2026
6 checks passed
@oguzhanunlu Oguzhan Unlu (oguzhanunlu) deleted the transient-reason branch June 8, 2026 11:17
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.

2 participants