Skip to content

Panic when trying to save equipment library (weapon-related?) #1015

@maw3193

Description

@maw3193

I've encountered a panic in gcs when saving an equipment library.

The stack trace for the panic is:

ERROR | 2025-12-28 | 16:05:22.226 | recovered from panic | xos/panic_recovery.go:33
        [encoding/json.(*encodeState).marshal.func1] encoding/json/encode.go:339
        [encoding/json.(*encodeState).marshal.func1] encoding/json/encode.go:339
        [encoding/json.(*encodeState).marshal.func1] encoding/json/encode.go:339
        [github.com/richardwilkes/gcs/v5/model/gurps.(*Weapon).DataOwner] github.com/richardwilkes/gcs/v5/model/gurps/weapon.go:452
        [github.com/richardwilkes/gcs/v5/model/gurps.(*Weapon).Entity] github.com/richardwilkes/gcs/v5/model/gurps/weapon.go:464
        [github.com/richardwilkes/gcs/v5/model/gurps.(*WeaponDamage).resolveDiceSpec] github.com/richardwilkes/gcs/v5/model/gurps/weapon_damage.go:479
        [github.com/richardwilkes/gcs/v5/model/gurps.(*WeaponDamage).formatDiceWithSub] github.com/richardwilkes/gcs/v5/model/gurps/weapon_damage.go:462
        [github.com/richardwilkes/gcs/v5/model/gurps.(*WeaponDamage).String] github.com/richardwilkes/gcs/v5/model/gurps/weapon_damage.go:144
        [github.com/richardwilkes/gcs/v5/model/gurps.(*WeaponDamage).ResolvedDamage] github.com/richardwilkes/gcs/v5/model/gurps/weapon_damage.go:295
        [github.com/richardwilkes/gcs/v5/model/gurps.(*Weapon).MarshalJSON] github.com/richardwilkes/gcs/v5/model/gurps/weapon.go:293
        [encoding/json.marshalerEncoder] encoding/json/encode.go:483
        [encoding/json.arrayEncoder.encode] encoding/json/encode.go:901
        [encoding/json.sliceEncoder.encode] encoding/json/encode.go:874
        [encoding/json.structEncoder.encode] encoding/json/encode.go:758
        [encoding/json.ptrEncoder.encode] encoding/json/encode.go:930
        [encoding/json.(*encodeState).reflectValue] encoding/json/encode.go:367
        [encoding/json.(*encodeState).marshal] encoding/json/encode.go:343
        [encoding/json.Marshal] encoding/json/encode.go:209
        [github.com/richardwilkes/gcs/v5/model/gurps.(*Equipment).MarshalJSON] github.com/richardwilkes/gcs/v5/model/gurps/equipment.go:256
        [encoding/json.marshalerEncoder] encoding/json/encode.go:483
        [encoding/json.arrayEncoder.encode] encoding/json/encode.go:901
        [encoding/json.sliceEncoder.encode] encoding/json/encode.go:874
        [encoding/json.structEncoder.encode] encoding/json/encode.go:758
        [encoding/json.ptrEncoder.encode] encoding/json/encode.go:930
        [encoding/json.(*encodeState).reflectValue] encoding/json/encode.go:367
        [encoding/json.(*encodeState).marshal] encoding/json/encode.go:343
        [encoding/json.Marshal] encoding/json/encode.go:209
        [github.com/richardwilkes/gcs/v5/model/gurps.(*Equipment).MarshalJSON] github.com/richardwilkes/gcs/v5/model/gurps/equipment.go:256
        [encoding/json.marshalerEncoder] encoding/json/encode.go:483
        [encoding/json.arrayEncoder.encode] encoding/json/encode.go:901
        [encoding/json.sliceEncoder.encode] encoding/json/encode.go:874
        [encoding/json.structEncoder.encode] encoding/json/encode.go:758
        [encoding/json.ptrEncoder.encode] encoding/json/encode.go:930
        [encoding/json.(*encodeState).reflectValue] encoding/json/encode.go:367
        [encoding/json.(*encodeState).marshal] encoding/json/encode.go:343
        [encoding/json.(*Encoder).Encode] encoding/json/stream.go:212
        [github.com/richardwilkes/gcs/v5/model/jio.Save] github.com/richardwilkes/gcs/v5/model/jio/save.go:42
        [github.com/richardwilkes/gcs/v5/model/jio.SaveToFile.func1] github.com/richardwilkes/gcs/v5/model/jio/save.go:30
        [github.com/richardwilkes/toolbox/v2/xos.WriteSafeFile] xos/safefile.go:44
        [github.com/richardwilkes/gcs/v5/model/jio.SaveToFile] github.com/richardwilkes/gcs/v5/model/jio/save.go:29
        [github.com/richardwilkes/gcs/v5/model/gurps.SaveEquipment] github.com/richardwilkes/gcs/v5/model/gurps/equipment.go:132
        [github.com/richardwilkes/gcs/v5/ux.NewEquipmentTableDockable.func1] github.com/richardwilkes/gcs/v5/ux/equipment_table.go:73
        [github.com/richardwilkes/gcs/v5/ux.SaveDockableAs] github.com/richardwilkes/gcs/v5/ux/workspace.go:652
        [github.com/richardwilkes/gcs/v5/ux.(*TableDockable[...]).save] github.com/richardwilkes/gcs/v5/ux/table_dockable.go:302
        [github.com/richardwilkes/gcs/v5/ux.NewTableDockable[...].func10] github.com/richardwilkes/gcs/v5/ux/table_dockable.go:130
        [github.com/richardwilkes/unison.(*Panel).PerformCmd.func1] panel.go:720
        [github.com/richardwilkes/toolbox/v2/xos.SafeCall] xos/panic_recovery.go:46
        [github.com/richardwilkes/unison.(*Panel).PerformCmd] panel.go:720
        [github.com/richardwilkes/unison.RouteActionToFocusExecuteFunc] action.go:90
        [github.com/richardwilkes/unison.(*Action).Execute.func1] action.go:69
        [github.com/richardwilkes/toolbox/v2/xos.SafeCall] xos/panic_recovery.go:46
        [github.com/richardwilkes/unison.(*Action).Execute] action.go:69
        [github.com/richardwilkes/unison.(*Action).execute] action.go:74
        [github.com/richardwilkes/unison.(*menuItem).execute.func1] menu_item.go:380
        [github.com/richardwilkes/toolbox/v2/xos.SafeCall] xos/panic_recovery.go:46
        [github.com/richardwilkes/unison.(*menuItem).execute] menu_item.go:380
        [github.com/richardwilkes/unison.(*menuItem).mouseUp] menu_item.go:189
        [github.com/richardwilkes/unison.(*Window).mouseUp.func2] window.go:1101
        [github.com/richardwilkes/toolbox/v2/xos.SafeCall] xos/panic_recovery.go:46
        [github.com/richardwilkes/unison.(*Window).mouseUp] window.go:1100
        [github.com/richardwilkes/unison.(*Window).mouseButtonCallback] window.go:343
        [github.com/go-gl/glfw/v3.3/glfw.goMouseButtonCB] input.go:333
        [_cgoexp_4aa16c696532_goMouseButtonCB] _cgo_gotypes.go:2655
        [github.com/go-gl/glfw/v3.3/glfw._Cfunc_glfwWaitEvents] _cgo_gotypes.go:2569
        [github.com/go-gl/glfw/v3.3/glfw.WaitEvents] window.go:949
        [github.com/richardwilkes/unison.processEvents] app.go:152
        [github.com/richardwilkes/unison.Start] app.go:147
        [github.com/richardwilkes/gcs/v5/ux.Start] github.com/richardwilkes/gcs/v5/ux/startup.go:34
        [main.main] main.go:101
      Caused by: runtime error: invalid memory address or nil pointer dereference

According to Help > About GCS, this is with version 5.42.0 and build 20251030215210.

Looking at the codebase for v5.42.0, that seems to be:

// DataOwner returns the weapon owner's data owner.
func (w *Weapon) DataOwner() DataOwner {
        if xreflect.IsNil(w.Owner) { // <-- this line here
                return nil
        }
        return w.Owner.DataOwner()
}

which looks like it should be safely checking if something's nil, so I'm not sure why that is erroring.

I've had this stack trace happen before, but intermittently, and I wasn't changing any equipment with weapons at the time.

For what it's worth, the equipment library that this happened with is attached:

Spaceships Equipment.eqp.json

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions