{"record":{"id":"4da1d5841bcf09fb","repo":"dagger/dagger","slug":"clone-detached-file-for-container-result-file-mus","errorCode":null,"errorMessage":"clone detached file for container result: file must be materialized, got lazy %T","messagePattern":"clone detached file for container result: file must be materialized, got lazy %T","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/container.go","lineNumber":917,"sourceCode":"\tquery, err := CurrentQuery(ctx)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treopened, err := query.SnapshotManager().GetBySnapshotID(ctx, snapshot.SnapshotID(), bkcache.NoUpdateLastUsed)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tcp.Snapshot.setValue(reopened)\n\treturn cp, nil\n}\n\n//nolint:dupl // symmetric with cloneDetachedDirectoryForContainerResult; sharing obscures type specifics\nfunc cloneDetachedFileForContainerResult(ctx context.Context, src *File) (*File, error) {\n\tif src == nil {\n\t\treturn nil, nil\n\t}\n\tif src.Lazy != nil {\n\t\treturn nil, fmt.Errorf(\"clone detached file for container result: file must be materialized, got lazy %T\", src.Lazy)\n\t}\n\n\tcp := &File{\n\t\tPlatform: src.Platform,\n\t\tServices: slices.Clone(src.Services),\n\t\tFile:     new(LazyAccessor[string, *File]),\n\t\tSnapshot: new(LazyAccessor[bkcache.ImmutableRef, *File]),\n\t}\n\tif filePath, ok := src.File.Peek(); ok {\n\t\tcp.File.setValue(filePath)\n\t}\n\n\tsnapshot, ok := src.Snapshot.Peek()\n\tif !ok || snapshot == nil {\n\t\treturn cp, nil\n\t}\n\n\tquery, err := CurrentQuery(ctx)","sourceCodeStart":899,"sourceCodeEnd":935,"githubUrl":"https://github.com/dagger/dagger/blob/82ba2681dbe30d3547a1dc50ea495900ab5b6047/core/container.go#L899-L935","documentation":"Symmetric with the directory case: cloneDetachedFileForContainerResult clones a *File for a container result and rejects files whose Lazy accessor is still set, since detached clone needs fully materialized file contents. The offending lazy type is reported via %T.","triggerScenarios":"A detach/export flow hands a lazily-backed *File (unevaluated accessor) to cloneDetachedFileForContainerResult — e.g. a File obtained from a container without first evaluating its contents.","commonSituations":"Exporting a lazily derived file (from container.File/copy) before its contents were resolved; engine bugs skipping file materialization; forks constructing File with Lazy non-nil.","solutions":["Evaluate/materialize the File before cloning so src.Lazy is cleared","Change the caller to handle lazy files by going through the standard (non-detached) copy path that performs evaluation","In custom code, construct File the same way the engine does — new(LazyAccessor[string, *File]) plus loaded content, no leftover Lazy"],"exampleFix":"// before\nif f.Lazy != nil {\n    cp, err := cloneDetachedFileForContainerResult(ctx, f) // errors: got lazy\n}\n// after\nf, err := f.Evaluate(ctx) // materialize file contents first\nif err != nil { return err }\ncp, err := cloneDetachedFileForContainerResult(ctx, f)","handlingStrategy":"validation","validationCode":"if file.Lazy != nil {\n    // materialize first: file, err = file.Evaluate(ctx)\n}\ncp, err := cloneDetachedFileForContainerResult(ctx, file)","typeGuard":"func isMaterializedFile(f *core.File) bool { return f == nil || f.Lazy == nil }","tryCatchPattern":null,"preventionTips":["Evaluate files before detached clone/export flows","Route lazily-derived files through standard copy paths that evaluate them","Add tests asserting detached file clones only receive materialized files"],"tags":["dagger","container","file","materialization"],"backgroundTag":"lazy-value-not-materialized","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"}