{"record":{"id":"738b1bed6ce44539","repo":"multica-ai/multica","slug":"chmod-temp-config-file-w","errorCode":null,"errorMessage":"chmod temp config file: %w","messagePattern":"chmod temp config file: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/cli/config.go","lineNumber":370,"sourceCode":"\n\t// Write to a temp file in the same directory, then rename for atomicity.\n\ttmp, err := os.CreateTemp(dir, \".config-*.json.tmp\")\n\tif err != nil {\n\t\treturn fmt.Errorf(\"create temp config file: %w\", err)\n\t}\n\ttmpPath := tmp.Name()\n\tif _, err := tmp.Write(append(data, '\\n')); err != nil {\n\t\ttmp.Close()\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"write temp config file: %w\", err)\n\t}\n\tif err := tmp.Close(); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"close temp config file: %w\", err)\n\t}\n\tif err := os.Chmod(tmpPath, 0o600); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"chmod temp config file: %w\", err)\n\t}\n\tif err := os.Rename(tmpPath, path); err != nil {\n\t\tos.Remove(tmpPath)\n\t\treturn fmt.Errorf(\"rename config file: %w\", err)\n\t}\n\treturn nil\n}\n","sourceCodeStart":352,"sourceCodeEnd":378,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/cli/config.go#L352-L378","documentation":"Before the final rename, the temp file is chmod'd to 0600 so the saved config is owner-only. That chmod failed — usually because the file was already gone (a concurrent cleaner) or because ownership changed mid-operation. The temp file is then removed and the save fails safely.","triggerScenarios":"A concurrent process (another CLI instance, a tmp cleaner, antivirus) deleting the temp file between creation and chmod; or ownership confusion when different users run the CLI against the same task-local root.","commonSituations":"Two CLI invocations racing to save the same profile; systemd-tmpfiles or a cron job cleaning dot-prefixed temp files; concurrent daemon and manual CLI writes to one MULTICA_TASK_CONFIG_ROOT.","solutions":["Serialize config saves per profile (a lockfile or running one CLI at a time) to eliminate the race","Exclude the config directory from temp-file cleaners","Ensure only one user account writes to a given task-local root","Simply retry the save — the next attempt will use a fresh temp file"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := cli.SaveCLIConfig(cfg); err != nil && errors.Is(err, os.ErrNotExist) {\n\t// temp file vanished (race with cleaner); retry the save\n\terr = cli.SaveCLIConfig(cfg)\n}","preventionTips":["Serialize concurrent config saves per profile (lockfile)","Exclude .config-*.json.tmp patterns from temp cleaners","Run only one user against each task-local root"],"tags":["filesystem","permissions","concurrency","go"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}