{"record":{"id":"c53a5f55d159b99a","repo":"wavetermdev/waveterm","slug":"failed-to-check-local-app-w","errorCode":null,"errorMessage":"failed to check local app: %w","messagePattern":"failed to check local app: %w","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/waveappstore/waveappstore.go","lineNumber":673,"sourceCode":"\tif err := ValidateAppId(newLocalAppId); err != nil {\n\t\treturn fmt.Errorf(\"invalid new app name: %w\", err)\n\t}\n\n\thomeDir := wavebase.GetHomeDir()\n\twaveappsDir := filepath.Join(homeDir, \"waveapps\")\n\n\toldLocalDir := filepath.Join(waveappsDir, AppNSLocal, appName)\n\tnewLocalDir := filepath.Join(waveappsDir, AppNSLocal, newAppName)\n\toldDraftDir := filepath.Join(waveappsDir, AppNSDraft, appName)\n\tnewDraftDir := filepath.Join(waveappsDir, AppNSDraft, newAppName)\n\n\t// Check if at least one of the apps exists\n\tlocalExists := false\n\tdraftExists := false\n\tif _, err := os.Stat(oldLocalDir); err == nil {\n\t\tlocalExists = true\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to check local app: %w\", err)\n\t}\n\n\tif _, err := os.Stat(oldDraftDir); err == nil {\n\t\tdraftExists = true\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to check draft app: %w\", err)\n\t}\n\n\tif !localExists && !draftExists {\n\t\treturn fmt.Errorf(\"app '%s' does not exist in local or draft namespace\", appName)\n\t}\n\n\t// Check if new app name already exists in either namespace\n\tif _, err := os.Stat(newLocalDir); err == nil {\n\t\treturn fmt.Errorf(\"local app '%s' already exists\", newAppName)\n\t} else if !os.IsNotExist(err) {\n\t\treturn fmt.Errorf(\"failed to check if new local app exists: %w\", err)\n\t}","sourceCodeStart":655,"sourceCodeEnd":691,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/waveappstore/waveappstore.go#L655-L691","documentation":"While checking whether the app exists, RenameLocalApp stats the old local directory. If os.Stat fails with an error other than NotExist (permission denied, I/O error, path issues), the function aborts with \"failed to check local app: %w\". This distinguishes real filesystem failures from a simply-missing app.","triggerScenarios":"os.Stat(oldLocalDir) returns a non-ENOENT error: the waveapps directory or its parents are unreadable, permissions deny access, or an I/O error occurs during the stat.","commonSituations":"Restrictive file permissions on ~/waveapps, the home directory moved or is on a failing/unmounted volume, running as a different user without access to the app directory.","solutions":["Check permissions on ~/waveapps (and the app's local/ subdirectory) and fix with chmod/chown","Verify the volume containing the home directory is mounted and healthy","Run the process as the user who owns the waveapps directory"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// pre-check access to the waveapps tree\nif err := os.Access(filepath.Join(wavebase.GetHomeDir(), \"waveapps\", \"local\"), os.R_OK); err != nil {\n    return fmt.Errorf(\"no read access to local apps dir: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"if err := waveappstore.RenameLocalApp(oldName, newName); err != nil {\n    var pe *fs.PathError\n    if strings.Contains(err.Error(), \"failed to check local app\") && errors.As(err, &pe) {\n        return fmt.Errorf(\"filesystem problem on %s: %w\", pe.Path, pe.Err)\n    }\n    return err\n}","preventionTips":["Ensure ~/waveapps is owned by and readable by the running user","Do not run app-management code as root or another user","Monitor disk health; stat failures often precede broader I/O problems"],"tags":["go","filesystem","permissions","os-stat"],"backgroundTag":"filesystem-permission-denied","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}