{"record":{"id":"3258bda113bde3c3","repo":"dagger/dagger","slug":"encode-persisted-service-host-socket-d-nil-socke","errorCode":null,"errorMessage":"encode persisted service host socket %d: nil socket","messagePattern":"encode persisted service host socket (.+?): nil socket","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/service.go","lineNumber":154,"sourceCode":"\t\tif err != nil {\n\t\t\treturn dagql.PersistedObjectEncoding{}, err\n\t\t}\n\t}\n\tif svc.ModuleContext.Self() != nil {\n\t\tpayload.ModuleContextResultID, err = encodePersistedObjectRef(cache, svc.ModuleContext, \"service module context\")\n\t\tif err != nil {\n\t\t\treturn dagql.PersistedObjectEncoding{}, err\n\t\t}\n\t}\n\tif svc.TunnelUpstream.Self() != nil {\n\t\tpayload.TunnelUpstreamResultID, err = encodePersistedObjectRef(cache, svc.TunnelUpstream, \"service tunnel upstream\")\n\t\tif err != nil {\n\t\t\treturn dagql.PersistedObjectEncoding{}, err\n\t\t}\n\t}\n\tfor i, sock := range svc.HostSockets {\n\t\tif sock == nil {\n\t\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted service host socket %d: nil socket\", i)\n\t\t}\n\t\tpayload.HostSockets = append(payload.HostSockets, persistedServiceHostSocket{\n\t\t\tKind:           sock.Kind,\n\t\t\tHandle:         sock.Handle,\n\t\t\tURLVal:         sock.URLVal,\n\t\t\tPortForwardVal: sock.PortForwardVal,\n\t\t\tSourceClientID: sock.SourceClientID,\n\t\t})\n\t}\n\tenc, err := json.Marshal(payload)\n\tif err != nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"marshal persisted service payload: %w\", err)\n\t}\n\treturn encodePersistedObjectRawJSON(enc), nil\n}\n\nfunc (*Service) DecodePersistedObject(ctx context.Context, dag *dagql.Server, _ uint64, _ *dagql.ResultCall, payload json.RawMessage) (dagql.Typed, error) {\n\tvar persisted persistedServicePayload","sourceCodeStart":136,"sourceCodeEnd":172,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/service.go#L136-L172","documentation":"While encoding a service for persistence, one of the entries in svc.HostSockets is a nil *Socket. Host sockets record host=>container socket forwards and must carry Kind/Handle/URL data; a nil entry would produce a corrupt payload, so encoding aborts with the index of the offending socket.","triggerScenarios":"Calling EncodePersistedObject (or persisting any result referencing the service) when svc.HostSockets contains a nil element — e.g. a socket forward registered with a nil *Socket, or HostSockets populated from a deserialized/legacy payload containing null entries.","commonSituations":"Host socket tunnels (Container.WithExposedPort / host tunnel features) whose socket handles were not properly initialized; results decoded from older cache formats with null hostSocket entries then re-persisted.","solutions":["Find where the nil Socket was appended to HostSockets and skip or error at registration time instead.","Filter out nil sockets before persisting: svc.HostSockets = slices.DeleteFunc(svc.HostSockets, func(s *Socket) bool { return s == nil }).","Clear the stale cache entry and re-create the host socket tunnel."],"exampleFix":"// before\nsvc.HostSockets = append(svc.HostSockets, sock) // sock may be nil\n// after\nif sock != nil {\n    svc.HostSockets = append(svc.HostSockets, sock)\n}","handlingStrategy":"validation","validationCode":"for i, sock := range svc.HostSockets {\n    if sock == nil {\n        return fmt.Errorf(\"host socket %d is nil before persisting\", i)\n    }\n}","typeGuard":"func hasNilSocket(svc *dagger.Service) bool {\n    for _, s := range svc.HostSockets { if s == nil { return true } }\n    return false\n}","tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"nil socket\") {\n    // drop nil sockets and re-persist, or recreate the host tunnel\n}","preventionTips":["Skip nil sockets when appending to HostSockets.","Re-create host socket tunnels after engine upgrades instead of reusing cached entries.","Validate socket registration return values before storing them."],"tags":["service","sockets","persistence","nil-pointer"],"backgroundTag":"nil-socket-in-persisted-service","analyzedSha":"82ba2681dbe30d3547a1dc50ea495900ab5b6047","analyzedAt":"2026-09-05T07:21:37.930Z","contentChangedAt":"2026-09-05T07:21:37.930Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}