{"record":{"id":"f3e6a2dedffe5596","repo":"docker/compose","slug":"can-t-access-os-tempdir-s-w","errorCode":null,"errorMessage":"can't access os.tempDir %s: %w","messagePattern":"can't access os\\.tempDir (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/compose/build_bake.go","lineNumber":291,"sourceCode":"\tif options.Print {\n\t\t_, err = fmt.Fprintln(s.stdout(), string(b))\n\t\treturn nil, err\n\t}\n\tlogrus.Debugf(\"bake build config:\\n%s\", string(b))\n\n\ttmpdir := os.TempDir()\n\tvar metadataFile string\n\tfor {\n\t\t// we don't use os.CreateTemp here as we need a temporary file name, but don't want it actually created\n\t\t// as bake relies on atomicwriter and this creates conflict during rename\n\t\tmetadataFile = filepath.Join(tmpdir, fmt.Sprintf(\"compose-build-metadataFile-%s.json\", uuid.New().String()))\n\t\tif _, err = os.Stat(metadataFile); err != nil {\n\t\t\tif os.IsNotExist(err) {\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tvar pathError *fs.PathError\n\t\t\tif errors.As(err, &pathError) {\n\t\t\t\treturn nil, fmt.Errorf(\"can't access os.tempDir %s: %w\", tmpdir, pathError.Err)\n\t\t\t}\n\t\t}\n\t}\n\tdefer func() {\n\t\t_ = os.Remove(metadataFile)\n\t}()\n\n\tbuildx, err := s.getBuildxPlugin()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\targs := []string{\"bake\", \"--file\", \"-\", \"--progress\", \"rawjson\", \"--metadata-file\", metadataFile}\n\t// FIXME we should prompt user about this, but this is a breaking change in UX\n\tfor _, path := range read {\n\t\targs = append(args, \"--allow\", \"fs.read=\"+path)\n\t}\n\tif privileged {","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/docker/compose/blob/ddc4b044b62e9f715212ea4143fa830fac76382f/pkg/compose/build_bake.go#L273-L309","documentation":"Before invoking buildx bake, compose generates a unique metadata-file name under os.TempDir() by stat-ing candidate names until one is free. If stat fails with an error other than NotExist — and is a *fs.PathError — the temp directory itself is considered unusable and this error wraps the underlying path error. It means the OS refused to stat inside the temp dir (permission denied, I/O error, or the path vanished).","triggerScenarios":"TMPDIR pointing to a directory the user cannot stat/read; TMPDIR removed or replaced while a build runs; a full or errored tmpfs; TMPDIR set to a path that is actually a file's broken symlink.","commonSituations":"Containers or CI runners with a custom TMPDIR that is missing or mode 000; hardened environments restricting /tmp access (noexec/locked-down tmpfs); TMPDIR exported with a typo; snap/containerized docker where the daemon's TMPDIR differs from the client's.","solutions":["Verify TMPDIR exists and is readable/writable: ls -ld \"$TMPDIR\" /tmp","Unset a broken TMPDIR or point it at a healthy directory: export TMPDIR=$(mktemp -d)","Clear stale files if /tmp is full or its metadata is corrupted","For containerized daemons, ensure the daemon container also has a valid temp dir"],"exampleFix":"# before\n$ export TMPDIR=/opt/tmp   # missing or 000 perms\n$ docker compose build\n# after\n$ sudo install -d -m 1777 /opt/tmp\n$ docker compose build\n","handlingStrategy":"validation","validationCode":"// Before a bake build in constrained environments:\ntmp := os.TempDir()\ninfo, err := os.Stat(tmp)\nif err != nil || !info.IsDir() || info.Mode().Perm()&0o200 == 0 {\n\treturn fmt.Errorf(\"temp dir %s missing or not writable\", tmp)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set TMPDIR explicitly to a known-good scratch dir in CI and containers","Avoid pointing TMPDIR at paths that can vanish mid-run (deleted job workspaces)","Give builders enough tmpfs space for build metadata and contexts"],"tags":["filesystem","temp-dir","bake","environment"],"backgroundTag":null,"analyzedSha":"ddc4b044b62e9f715212ea4143fa830fac76382f","analyzedAt":"2026-08-15T13:31:42.319Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}