Skip to content

Fix IdCardConsoleSystem missing prototype error#42884

Open
Tayrtahn wants to merge 1 commit intospace-wizards:masterfrom
Tayrtahn:fix/idcardconsole-emptystring
Open

Fix IdCardConsoleSystem missing prototype error#42884
Tayrtahn wants to merge 1 commit intospace-wizards:masterfrom
Tayrtahn:fix/idcardconsole-emptystring

Conversation

@Tayrtahn
Copy link
Member

About the PR

Fixed a prototype indexing error in IdCardConsoleSystem.

Why / Balance

Bug fix. Grafana logs show this error frequently:

Attempted to resolve invalid ProtoId<JobPrototype>:
   at System.Environment.get_StackTrace()
   at Robust.Shared.Prototypes.PrototypeManager.Resolve[T](ProtoId`1 id, T& prototype) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Shared/Prototypes/PrototypeManager.cs:line 822
   at Content.Server.Access.Systems.IdCardConsoleSystem.TryWriteToTargetId(EntityUid uid, String newFullName, String newJobTitle, List`1 newAccessList, ProtoId`1 newJobProto, EntityUid player, IdCardConsoleComponent component) in /home/runner/work/space-station-14/space-station-14/Content.Server/Access/Systems/IdCardConsoleSystem.cs:line 149
   at Content.Server.Access.Systems.IdCardConsoleSystem.OnWriteToTargetIdMessage(EntityUid uid, IdCardConsoleComponent component, WriteToTargetIdMessage args) in /home/runner/work/space-station-14/space-station-14/Content.Server/Access/Systems/IdCardConsoleSystem.cs:line 65
   at Robust.Shared.GameObjects.EntityEventBus.EntDispatch(EntityUid euid, Type eventType, Unit& args) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Shared/GameObjects/EntityEventBus.Directed.cs:line 572
   at Robust.Shared.GameObjects.SharedUserInterfaceSystem.OnMessageReceived(BoundUIWrapMessage msg, EntityUid sender) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Shared/GameObjects/Systems/SharedUserInterfaceSystem.cs:line 146
   at Robust.Server.GameObjects.ServerEntityManager.DispatchEntityNetworkMessage(MsgEntity message) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/GameObjects/ServerEntityManager.cs:line 230
   at Robust.Server.GameObjects.ServerEntityManager.TickUpdate(Single frameTime, Boolean noPredictions, Histogram histogram) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/GameObjects/ServerEntityManager.cs:line 166
   at Robust.Server.BaseServer.Update(FrameEventArgs frameEventArgs) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/BaseServer.cs:line 733
   at Robust.Shared.Timing.GameLoop.Run() in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Shared/Timing/GameLoop.cs:line 243
   at Robust.Server.BaseServer.MainLoop() in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/BaseServer.cs:line 587
   at Robust.Server.Program.ParsedMain(CommandLineArgs args, Boolean contentStart, ServerOptions options) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/Program.cs:line 74
   at Robust.Server.Program.Start(String[] args, ServerOptions options, Boolean contentStart) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/Program.cs:line 42
   at Robust.Server.Program.Main(String[] args) in /home/runner/work/space-station-14/space-station-14/RobustToolbox/Robust.Server/Program.cs:line 25
Sawmill=proto

Technical details

The error comes from this PrototypeManager.Resolve call on line 149:

if (_prototype.Resolve(newJobProto, out var job)
&& _prototype.Resolve(job.Icon, out var jobIcon))
{
_idCard.TryChangeJobIcon(targetId, jobIcon, player: player);
_idCard.TryChangeJobDepartment(targetId, job);
}

which sometimes gets an empty string for newJobProto, which fails to be resolved and logs an error.

Why does it sometimes get an empty string? Because of this bit of logic in the UI:

// Don't send this if it isn't dirty.
var jobProtoDirty = _lastJobProto != null &&
_jobPrototypeIds[JobPresetOptionButton.SelectedId] != _lastJobProto;
_owner.SubmitData(
FullNameLineEdit.Text,
JobTitleLineEdit.Text,
// Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair
_accessButtons.ButtonsList.Where(x => x.Value.Pressed).Select(x => x.Key).ToList(),
jobProtoDirty ? _jobPrototypeIds[JobPresetOptionButton.SelectedId] : string.Empty);

which explicitly sends an empty string if the value hasn't changed. This makes it so that the job icon and department only get set when a job preset it chosen from the list, instead of every time an access is changed.

While we could add a check for an empty string before the Resolve, using an empty string to indicate "no change" is a bit clumsy. Instead, the protoid passed in the BUI message is now nullable and uses null to indicate no change. PrototypeManager.Resolve returns false without logging an error if the passed protoid is null, so there is no longer an issue.

Requirements

Breaking changes

IdCardConsoleComponent.WriteToTargetIdMessage.JobPrototype is now nullable.

@Tayrtahn Tayrtahn added T: Bugfix Type: Bugs and/or bugfixes P3: Standard Priority: Default priority for repository items. D3: Low Difficulty: Some codebase knowledge required. A: Command Area: Command department, where it isn't applicable to other departments. labels Feb 10, 2026
@PJBot PJBot added S: Approved Status: Reviewed and approved by at least one maintainer; a PR may require another approval. Changes: UI Changes: Might require knowledge of UI design or code. S: Needs Review Status: Requires additional reviews before being fully accepted. Not to be replaced by S: Approved. size/S Denotes a PR that changes 10-99 lines. labels Feb 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A: Command Area: Command department, where it isn't applicable to other departments. Changes: UI Changes: Might require knowledge of UI design or code. D3: Low Difficulty: Some codebase knowledge required. P3: Standard Priority: Default priority for repository items. S: Approved Status: Reviewed and approved by at least one maintainer; a PR may require another approval. S: Needs Review Status: Requires additional reviews before being fully accepted. Not to be replaced by S: Approved. size/S Denotes a PR that changes 10-99 lines. T: Bugfix Type: Bugs and/or bugfixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants