{"record":{"id":"0ede3f45eec16d72","repo":"dagger/dagger","slug":"get-or-init-call-empty-session-id","errorCode":null,"errorMessage":"get or init call: empty session ID","messagePattern":"get or init call: empty session ID","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"dagql/cache.go","lineNumber":4267,"sourceCode":"\t\tres.cacheUsageRecordTypeByID = recordTypeByIdentity\n\n\t\trecordTypes := cacheUsageRecordTypesFromMap(recordTypeByIdentity)\n\t\tif len(recordTypes) > 0 {\n\t\t\tres.recordType = cacheUsagePrimaryRecordType(recordTypes, \"\")\n\t\t}\n\t}\n}\n\n// Core cache lookup/insert flow is intentionally centralized here.\nfunc (c *Cache) GetOrInitCall(\n\tctx context.Context,\n\tsessionID string,\n\tresolver TypeResolver,\n\treq *CallRequest,\n\tfn func(context.Context) (AnyResult, error),\n) (AnyResult, error) {\n\tif sessionID == \"\" {\n\t\treturn nil, errors.New(\"get or init call: empty session ID\")\n\t}\n\top, err := c.beginSessionOperation(sessionID)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"get or init call: %w\", err)\n\t}\n\tres, callErr := c.getOrInitCall(ctx, sessionID, resolver, req, fn)\n\tif op.finish(callErr == nil && res != nil) {\n\t\treturn nil, fmt.Errorf(\"get or init call: %w: %q\", ErrCacheSessionReleased, sessionID)\n\t}\n\treturn res, callErr\n}\n\nfunc (c *Cache) getOrInitCall(\n\tctx context.Context,\n\tsessionID string,\n\tresolver TypeResolver,\n\treq *CallRequest,\n\tfn func(context.Context) (AnyResult, error),","sourceCodeStart":4249,"sourceCodeEnd":4285,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/dagql/cache.go#L4249-L4285","documentation":"Cache.getOrInitCall requires a non-empty session ID because results are scoped per client session. When it is called with an empty session ID, dagql rejects the call immediately rather than caching it under an anonymous session. A companion wrap ('get or init call: %w') covers failures from the session operation setup or the nested call.","triggerScenarios":"Calling GetOrInitCall/getOrInitCall with sessionID == \"\" — e.g. client metadata missing from the context when the session ID was extracted; constructing CallRequests outside a client session; SDK plumbing that fails to propagate the session header.","commonSituations":"Embedded dagger usage invoking the GraphQL layer without a client session; tests hitting the cache directly without setting up a session; upgrades where session metadata moved in the context and code reads the old key.","solutions":["Ensure a valid session ID is passed: obtain it from engine.ClientMetadata(ctx) and fail fast if it's empty before calling the cache.","Set up a client session (as the engine does per client connection) before issuing calls.","In tests, populate a fake session ID in context metadata.","Check that custom plumbing doesn't drop the session ID when constructing CallRequest."],"exampleFix":"// before\nres, err := cache.GetOrInitCall(ctx, \"\", resolver, req, fn)\n\n// after\nmeta, err := engine.ClientMetadataFromContext(ctx)\nif err != nil || meta.SessionID == \"\" {\n\treturn nil, errors.New(\"no client session for call\")\n}\nres, err := cache.GetOrInitCall(ctx, meta.SessionID, resolver, req, fn)","handlingStrategy":"validation","validationCode":"meta, err := engine.ClientMetadataFromContext(ctx)\nif err != nil || meta.SessionID == \"\" {\n\treturn errors.New(\"client session required before calling the cache\")\n}","typeGuard":null,"tryCatchPattern":"if _, err := cache.GetOrInitCall(ctx, sessionID, resolver, req, fn); err != nil {\n\tif strings.Contains(err.Error(), \"empty session ID\") {\n\t\treturn fmt.Errorf(\"missing client session: %w\", err)\n\t}\n\treturn err\n}","preventionTips":["Extract session IDs from client metadata and validate before cache calls.","Never invoke the GraphQL/cache layer outside a client session in tests or embedded use.","Keep session metadata propagation intact through custom SDK plumbing."],"tags":["dagql","cache","session-id","validation"],"backgroundTag":"missing-session-id","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"}