Skip to content

Guard spec.loadVolume access in doUpdate to avoid nil-index crash#499

Open
206airmail wants to merge 1 commit into
loki79uk:mainfrom
206airmail:fix/doupdate-loadvolume-nil-guard
Open

Guard spec.loadVolume access in doUpdate to avoid nil-index crash#499
206airmail wants to merge 1 commit into
loki79uk:mainfrom
206airmail:fix/doupdate-loadvolume-nil-guard

Conversation

@206airmail
Copy link
Copy Markdown

Problem

doUpdate crashes for vehicles where spec.loadVolume is nil — either on a multiplayer client (where initialiseTransformGroups never runs because it's gated on self.isServer) or for vehicles UAL detects as autoload-capable but that lack a configured loadArea. The pcall in onUpdate / onUpdateTick catches it, prints UAL - FATAL ERROR: <vehicle> once, and permanently disables UAL on that vehicle for the rest of the session.

Example log entries:

UAL - FATAL ERROR: TRAIL_KING Trailking 70HDG
UniversalAutoload.lua:2588: attempt to index nil with 'length'
UAL - FATAL ERROR: Phiber Tote Deck
UniversalAutoload.lua:2588: attempt to index nil with 'length'

Root cause

spec.loadVolume is only created in initialiseTransformGroups, called from onLoad only when:

if self.isServer and self.propertyState ~= VehiclePropertyState.SHOP_CONFIG then
    ...
    UniversalAutoload.initialiseTransformGroups(self)
end

So on a multiplayer client spec.loadVolume is always nil; on the server it's also nil whenever a vehicle has no valid loadArea config. The customOffset/customRotation block in doUpdate dereferences spec.loadVolume.length unconditionally (lines 2588 and 2592), hence the crash.

Fix

Wrap the offset/rotation block with if spec.loadVolume then ... end. The action-event update block above it (toggle loading, cycle material, etc.) does not depend on loadVolume and continues to run. No behavior change for vehicles where loadVolume is correctly populated.

spec.loadVolume is only created in initialiseTransformGroups, which is
called from onLoad only when self.isServer and the vehicle is not in
SHOP_CONFIG. On a multiplayer client, or for vehicles UAL detects as
autoload-capable but that lack a configured loadArea, spec.loadVolume
is therefore nil.

The customOffset/customRotation block in doUpdate dereferences
spec.loadVolume.length unconditionally, producing repeated
"UAL - FATAL ERROR: <vehicle>" log spam via the pcall in
onUpdate/onUpdateTick and permanently disabling UAL on the vehicle.

Wrap the offset/rotation block with `if spec.loadVolume then ... end`.
The action-event update block above is unaffected and continues to run.
@loki79uk
Copy link
Copy Markdown
Owner

loki79uk commented May 24, 2026

I'm away from home so I can't look until later in the week, but we should identify why the loading volume object was used by the client. Guarding access is a sticking plaster rather than a fix.

@206airmail
Copy link
Copy Markdown
Author

Good catch — diving in further, the loadVolume access is a symptom of a deeper MP issue rather than the bug itself.

Tracing the customOffset/customRotation feature end-to-end:

  1. InputkeyDown_left/right/rotate (UniversalAutoload.lua:838–857) set spec.leftKeyPressed etc. on the input-controlling client.
  2. Update — the block at UniversalAutoload.lua:2585–2615 (inside if self.isClient and ... isActiveForInputIgnoreSelection) reads those flags and mutates spec.customOffset / spec.customRotation, clamping with spec.loadVolume.length.
  3. ConsumerbuildObjectsToUnloadTable (UniversalAutoload.lua:3667–3672) reads spec.customOffset / spec.customRotation and applies them via setTranslation(spec.unloadGroup, …). That function is only called from startUnloading, gated by if self.isServer (UniversalAutoload.lua:1239).

No event ever syncs customOffset / customRotation from client to server. I grepped the whole repo including events/ — nothing. So in MP:

  • On a non-host client, the update block crashes on the first input tick (the bug this PR papers over), because initialiseTransformGroups only runs server-side, leaving spec.loadVolume == nil on every client.
  • Even if it didn't crash, the mutations would only ever live on the client and never reach the server, so the unload-position adjust feature is effectively non-functional in MP today.

(Worth noting up front: this is all about the runtime spec.loadVolume struct built by initialiseTransformGroups. The shop-editor spec.loadingVolume LoadingVolume instance is a separate object, lives only during shop config, and isn't touched by any of this — so the options below don't affect the in-shop autoload zone editor.)

So the real fix is one of:

  1. Make the adjustment server-side. Change the doUpdate block from if self.isClient to if self.isServer (it already runs in SP because server == client there), and forward the key state from client to server via a new event — e.g. SetUnloadAdjustEvent that fires from the keyDown handlers carrying {leftKeyPressed, rightKeyPressed, rotateKeyPressed}. Server applies the update against its own loadVolume. Cleanest, but adds an event and event handler.
  2. Keep client-side responsiveness, sync values back to server. Sync loadVolume.width/height/length in onReadStream/onWriteStream so the client has bounds, and add a SetUnloadOffsetEvent fired when customOffset / customRotation change. (Only the runtime loadVolume dimensions — the shop loadingVolume is unaffected.) More wire traffic, but lets the client see live feedback if you add any UI later.
  3. Skip in MP for now, leave a TODO. Keep my guard but mark the feature as SP-only until the sync is built out.

Happy to do whichever direction you prefer when you're back — option 1 feels right to me. The guard in this PR keeps logs clean in the meantime without changing functional behavior (it's already a no-op on MP clients).

@loki79uk
Copy link
Copy Markdown
Owner

Okay ChatGPT.

@206airmail
Copy link
Copy Markdown
Author

Yes, your not wrong..... I only have so much time in life to devote to hobbies, and while i wish i had the time to properly learn coding i have more important IRL things that take up my time. I'm just trying to help solve an issue on a really cool mod!

loki79uk added a commit that referenced this pull request May 25, 2026
This should have been SP only for now.  MP requires synchronisation of server only values with client.  Also needed for debug display.
@loki79uk
Copy link
Copy Markdown
Owner

No problem, just reporting the issue is good enough, but I appreciate the extra effort :D

Should be fixed now in https://github.com/loki79uk/FS25_UniversalAutoload/releases/tag/v1.0.2.8

Please test and let me know.

@206airmail
Copy link
Copy Markdown
Author

I was gone for a couple days, i'll test it in a bit.

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