Skip to content

fix: stop retrying license returns that can never succeed - #274

Merged
frostebite merged 2 commits into
mainfrom
fix/license-return-permanent-failures
Sep 14, 2026
Merged

frostebite merged 2 commits into
mainfrom
fix/license-return-permanent-failures

Conversation

@frostebite

@frostebite frostebite commented Sep 14, 2026

Copy link
Copy Markdown
Member

Reported in Discord

we spend an extra 2-3m at the end of the test action trying to return a license, which will fail every time

Reproduced in this repo's own licensing capability matrix, which had been emitting the identical warning unnoticed on every serial cell:

[Licensing::Module] Error: Access token is unavailable; failed to update
[Licensing::Module] Error: Failed to return entitlement license
[Licensing::Client] An error occurred attempting to return the ULF license
  (status code: 1400, message: "Machine bindings don't match")
License return failed with a known-transient licensing error (attempt 1/4) - retrying in 20s...

Cause

A machine-binding mismatch on return is permanent for the same reason it is on activation — the entitlement is bound to the machine that activated it. It was being retried because the same failing return also emits Access token is unavailable, which is in the transient list, so the real reason was masked and all four attempts burned: 20+40+80s of backoff before warning anyway.

Exactly the shape of the activation-side bug fixed in #264. Same masking, same wasted budget, opposite end of the lifecycle.

Changes

Both applied to all four return scripts:

  1. Permanent-failure guard — breaks out immediately, so the step ends in seconds rather than ~2.5 minutes. That's the reporter's actual complaint.
  2. The warning names the cause. "This seat may still be held by Unity's license server" sends people hunting a leak on their Unity account, when the licence was bound to a machine that no longer exists. It now says that, and says no action is needed.

Scope note

Confirmed by machine id in a single matrix job:

stage Machine Id
activation I+Yk5/H/JFuzwWwFQp3B6Yo46d4=
return ×4 BvJyyTlQnbSn3y+BZ6WqttLX5wM=

That particular split is specific to the matrix, which runs activate and return-license as separate commands and therefore separate containers; a normal build sources both in one container via runsteps.sh. I'm calling that out rather than claiming it explains every report — the retry-burn and the misleading warning are general, the container split is not.

Tests

Three, all verified to fail with the guard disabled. The editor stub now honours STUB_OUTPUT (the return paths drive the editor, not the licensing client), and this case defines its own stub because earlier cases redefine the shared one.

Suites: 67 bash, 34 PowerShell.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved license return handling when machine bindings do not match.
    • Prevented misleading transient-error messages and unnecessary retries in this scenario.
    • Added clearer messaging for the machine-binding cause.
    • Suppressed incorrect warnings about a leaked license seat.

Reported in Discord: "we spend an extra 2-3m at the end of the test
action trying to return a license, which will fail every time."

Reproduced in this repo's own licensing capability matrix, which had been
emitting the identical warning unnoticed on every serial cell:

  [Licensing::Module] Error: Access token is unavailable; failed to update
  [Licensing::Module] Error: Failed to return entitlement license
  [Licensing::Client] An error occurred attempting to return the ULF
    license (status code: 1400, message: "Machine bindings don't match")
  License return failed with a known-transient licensing error (attempt 1/4)

A machine-binding mismatch on return is permanent for the same reason it
is on activation: the entitlement is bound to the machine that activated
it. It was being retried because the same failing return also emits
"Access token is unavailable", which IS in the transient list - so the
real reason was masked and all four attempts burned, 20+40+80s of backoff
before warning anyway. Exactly the shape of the activation-side bug fixed
in #264.

Two changes, both applied to all four return scripts:

- A permanent-failure guard breaks out immediately, so the step ends in
  seconds instead of ~2.5 minutes.
- The warning names the actual cause. "This seat may still be held by
  Unity's license server" sends people hunting a leak on their Unity
  account, when in fact the licence was bound to a machine that no longer
  exists. It now says so, and says no action is needed.

Confirmed by machine id, in one matrix job: activation reported
I+Yk5/H/JFuzwWwFQp3B6Yo46d4= and all four return attempts reported
BvJyyTlQnbSn3y+BZ6WqttLX5wM=. That particular split is specific to the
matrix, which runs `activate` and `return-license` as separate commands
and therefore separate containers; a normal build sources both in one
container via runsteps.sh. The retry-burn and the misleading warning are
not specific to it.

Three tests, all verified to fail with the guard disabled. The editor
stub now honours STUB_OUTPUT, since the return paths drive the editor
rather than the licensing client, and this case defines its own stub
because earlier cases redefine the shared one.

Suites: 67 bash, 34 PowerShell.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 14, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (5)
  • dist/platforms/mac/steps/return_license.sh is excluded by !**/dist/**
  • dist/platforms/ubuntu/steps/return_license.sh is excluded by !**/dist/**
  • dist/platforms/windows/return_license.ps1 is excluded by !**/dist/**
  • dist/platforms/windows/steps/return_license.ps1 is excluded by !**/dist/**
  • src/generated/embedded-assets.ts is excluded by !**/generated/**

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: e3988956-d8d3-4162-873f-aabfbf3ccb13

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 691d45e1-ad28-4607-b3d0-3706c7594ccb

📥 Commits

Reviewing files that changed from the base of the PR and between b971614 and b945bd6.

⛔ Files ignored due to path filters (5)
  • dist/platforms/mac/steps/return_license.sh is excluded by !**/dist/**
  • dist/platforms/ubuntu/steps/return_license.sh is excluded by !**/dist/**
  • dist/platforms/windows/return_license.ps1 is excluded by !**/dist/**
  • dist/platforms/windows/steps/return_license.ps1 is excluded by !**/dist/**
  • src/generated/embedded-assets.ts is excluded by !**/generated/**
📒 Files selected for processing (1)
  • scripts/test-licensing-steps.sh

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The licensing test script now supports injected editor output and exit status. It adds regression coverage for a machine-binding return failure and verifies that the failure does not trigger retries or a leaked-seat warning.

Changes

Licensing return regression

Layer / File(s) Summary
Stub control and return-path regression
scripts/test-licensing-steps.sh
The editor stub accepts configured output and exit status. The regression test validates machine-binding diagnostics, retry suppression, and leaked-seat warning suppression.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to b945b

The regression coverage is isolated from later tests and introduces no identified merge-blocking risk.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: preventing retries for license returns that cannot succeed.
Description check ✅ Passed The description explains the cause, scope, implementation, and tests. It includes a Changes section, but it does not include the template's Checklist section or explicitly confirm the Readme status.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/license-return-permanent-failures

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The new warning told users "Node-locked serial activations are released
by Unity on their own; no action is needed." That was never verified.
Unity Pro serials have a finite number of activations, so if they are not
released, reassuring someone that nothing is needed could let them
exhaust the limit and then be surprised by it.

Replaced with what is actually known: the return failed because of a
machine binding, that is expected when activation and return happen on
different machines, and if activations later run out they can be released
at id.unity.com.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@frostebite
frostebite merged commit aae44e9 into main Sep 14, 2026
23 checks passed
@frostebite
frostebite deleted the fix/license-return-permanent-failures branch September 14, 2026 21:57
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.

1 participant