{"record":{"id":"09e9146b926ccc7d","repo":"multica-ai/multica","slug":"s-q-uses-unsupported-user-expansion","errorCode":null,"errorMessage":"%s %q uses unsupported ~user expansion","messagePattern":"(.+?) %q uses unsupported ~user expansion","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/internal/daemon/execenv/codex_home.go","lineNumber":1227,"sourceCode":"// resolveCodexConfigPath maps a path-valued config.toml entry to its source\n// file on this host. key is the config key the path came from and only shapes\n// the diagnostics, so an operator reading a failure knows which setting to fix.\n// A relative path resolves against the shared Codex home — that is the\n// directory the config was copied from, and the base Codex itself would have\n// used before the per-task home relocated CODEX_HOME.\nfunc resolveCodexConfigPath(configPath, sharedHome, key string) (string, error) {\n\tif filepath.IsAbs(configPath) {\n\t\treturn filepath.Clean(configPath), nil\n\t}\n\tif strings.HasPrefix(configPath, \"~/\") || strings.HasPrefix(configPath, `~\\`) {\n\t\thome, err := os.UserHomeDir()\n\t\tif err != nil {\n\t\t\treturn \"\", fmt.Errorf(\"resolve %s %q: user home: %w\", key, configPath, err)\n\t\t}\n\t\treturn filepath.Join(home, configPath[2:]), nil\n\t}\n\tif strings.HasPrefix(configPath, \"~\") {\n\t\treturn \"\", fmt.Errorf(\"%s %q uses unsupported ~user expansion\", key, configPath)\n\t}\n\treturn filepath.Join(sharedHome, filepath.Clean(configPath)), nil\n}\n\nfunc exposeSharedCodexPluginCache(codexHome, sharedHome string) error {\n\tsrc := filepath.Join(sharedHome, \"plugins\", \"cache\")\n\tdst := filepath.Join(codexHome, \"plugins\", \"cache\")\n\tif err := os.MkdirAll(src, 0o755); err != nil {\n\t\treturn fmt.Errorf(\"create shared plugin cache dir: %w\", err)\n\t}\n\tif err := os.MkdirAll(filepath.Dir(dst), 0o755); err != nil {\n\t\treturn fmt.Errorf(\"create codex plugin dir: %w\", err)\n\t}\n\n\tif fi, err := os.Lstat(dst); err == nil {\n\t\tisLink := fi.Mode()&os.ModeSymlink != 0\n\t\tif isLink {\n\t\t\tif target, readlinkErr := os.Readlink(dst); readlinkErr == nil && target == src {","sourceCodeStart":1209,"sourceCodeEnd":1245,"githubUrl":"https://github.com/multica-ai/multica/blob/2c0912b6ec764b373d44eeea1e80f0d9f11ab417/server/internal/daemon/execenv/codex_home.go#L1209-L1245","documentation":"A config path beginning with ~ but not ~/ (e.g. ~alice/codex.toml) cannot be expanded: per-user ~name expansion is deliberately unsupported by this resolver, which only handles the current user's home and shared-home-relative paths.","triggerScenarios":"A Codex config value set to another user's home path like ~shared/config.toml; a literal path that happens to start with a tilde.","commonSituations":"Config authored for multi-user setups copied into the daemon; docs or templates using ~user syntax.","solutions":["Replace ~user/... in the config value with the absolute path to that user's file","Move the file under the shared Codex home and reference it relatively"],"exampleFix":"# before\nauth_file = \"~alice/.codex/auth.json\"\n\n# after\nauth_file = \"/home/alice/.codex/auth.json\"","handlingStrategy":"validation","validationCode":"if strings.HasPrefix(configPath, \"~\") && !strings.HasPrefix(configPath, \"~/\") && !strings.HasPrefix(configPath, `~\\`) {\n\treturn fmt.Errorf(\"~user expansion unsupported; use an absolute path\")\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Lint Codex configs for ~user-style paths before deploying","Use absolute paths for cross-user references"],"tags":["config","codex","path-expansion"],"backgroundTag":null,"analyzedSha":"2c0912b6ec764b373d44eeea1e80f0d9f11ab417","analyzedAt":"2026-08-15T13:25:18.241Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}