{"record":{"id":"8017cc8424bd446d","repo":"dagger/dagger","slug":"encode-persisted-llm-variable-nil-llm-variable","errorCode":null,"errorMessage":"encode persisted LLM variable: nil LLM variable","messagePattern":"encode persisted LLM variable: nil LLM variable","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/llm.go","lineNumber":2737,"sourceCode":"\tHash string `field:\"true\"`\n}\n\nvar _ dagql.Typed = (*LLMVariable)(nil)\nvar _ dagql.PersistedObject = (*LLMVariable)(nil)\nvar _ dagql.PersistedObjectDecoder = (*LLMVariable)(nil)\n\nfunc (v *LLMVariable) Type() *ast.Type {\n\treturn &ast.Type{\n\t\tNamedType: \"LLMVariable\",\n\t\tNonNull:   true,\n\t}\n}\n\nfunc (v *LLMVariable) EncodePersistedObject(ctx context.Context, cache dagql.PersistedObjectCache) (dagql.PersistedObjectEncoding, error) {\n\t_ = ctx\n\t_ = cache\n\tif v == nil {\n\t\treturn dagql.PersistedObjectEncoding{}, fmt.Errorf(\"encode persisted LLM variable: nil LLM variable\")\n\t}\n\treturn encodePersistedObjectPayload(v)\n}\n\nfunc (*LLMVariable) DecodePersistedObject(ctx context.Context, dag *dagql.Server, _ uint64, _ *dagql.ResultCall, payload json.RawMessage) (dagql.Typed, error) {\n\t_ = ctx\n\t_ = dag\n\tvar v LLMVariable\n\tif err := json.Unmarshal(payload, &v); err != nil {\n\t\treturn nil, fmt.Errorf(\"decode persisted LLM variable payload: %w\", err)\n\t}\n\treturn &v, nil\n}\n\nfunc (llm *LLM) TokenUsage(ctx context.Context, dag *dagql.Server) (*LLMTokenUsage, error) {\n\tvar res LLMTokenUsage\n\tfor _, msg := range llm.Messages {\n\t\tif msg.TokenUsage == nil {","sourceCodeStart":2719,"sourceCodeEnd":2755,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/llm.go#L2719-L2755","documentation":"LLMVariable.EncodePersistedObject refuses to encode a nil *LLMVariable receiver when persisting it as a cache/persisted object. Encoding a nil value would produce a meaningless payload that couldn't be decoded back, so it is rejected explicitly.","triggerScenarios":"Passing a nil *LLMVariable into the persisted-object encoding path, e.g. an LLM environment variable slot that was never populated but got scheduled for cache persistence.","commonSituations":"Programmatically built LLM environments where a variable pointer was left nil; reflection-driven code paths that don't check for nil before persisting.","solutions":["Ensure the LLMVariable is fully constructed before it reaches the persistence layer","Guard callers with a nil check and skip persistence for nil variables","Investigate why a nil variable entered the environment (uninitialized env binding)"],"exampleFix":"// before\nvar v *LLMVariable\nenc, err := v.EncodePersistedObject(ctx, cache)\n// after\nif v == nil {\n    return errors.New(\"no LLM variable to persist\")\n}\nenc, err := v.EncodePersistedObject(ctx, cache)","handlingStrategy":"type-guard","validationCode":"if v == nil {\n    return errors.New(\"cannot persist nil LLM variable\")\n}","typeGuard":"func (v *LLMVariable) isPersistable() bool { return v != nil && v.Name != \"\" }","tryCatchPattern":null,"preventionTips":["Initialize LLMVariable values before adding them to the environment","Skip nil entries when persisting environment variables","Add nil checks at environment-construction boundaries"],"tags":["llm","persistence","nil-pointer"],"backgroundTag":"nil-value-encoding","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"}