{"record":{"id":"ed283a49877f57da","repo":"asdf-vm/asdf","slug":"dynamic-msg-passed-to-printerror","errorCode":null,"errorMessage":"<dynamic msg passed to printError>","messagePattern":"<dynamic msg passed to printError>","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/cli/set/set.go","lineNumber":98,"sourceCode":"\n\t\terr = toolversions.WriteToolVersionsToFile(path, []toolversions.ToolVersions{tv})\n\t\tif err != nil {\n\t\t\terr = printError(stderr, fmt.Sprintf(\"error writing version file: %s\", err))\n\t\t}\n\t\treturn err\n\t}\n\n\t// Write new file in current dir\n\tfilepath := filepath.Join(currentDir, conf.DefaultToolVersionsFilename)\n\treturn toolversions.WriteToolVersionsToFile(filepath, []toolversions.ToolVersions{tv})\n}\n\nfunc printError(stderr io.Writer, msg string) error {\n\tif !strings.HasSuffix(msg, \"\\n\") {\n\t\tmsg += \"\\n\"\n\t}\n\tfmt.Fprint(stderr, msg)\n\treturn errors.New(strings.TrimSuffix(msg, \"\\n\"))\n}\n\nfunc findVersionFileInParentDir(conf config.Config, directory string) (string, bool) {\n\tdirectory = filepath.Dir(directory)\n\n\tfor {\n\t\tpath := filepath.Join(directory, conf.DefaultToolVersionsFilename)\n\t\tif _, err := os.Stat(path); err == nil {\n\t\t\treturn path, true\n\t\t}\n\n\t\tif directory == \"/\" {\n\t\t\treturn \"\", false\n\t\t}\n\n\t\tdirectory = filepath.Dir(directory)\n\t}\n}","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/asdf-vm/asdf/blob/074a1722ca88d6677f228541ce06efaf4f9924d4/internal/cli/set/set.go#L80-L116","documentation":"printError in internal/cli/set writes the given message to stderr (ensuring a trailing newline) and returns it as a new error. This is the generic failure path for the `asdf set` command, so the message is dynamic — it describes whatever validation or filesystem problem occurred.","triggerScenarios":"Any failure inside `asdf set` handling that Main routes through printError: invalid arguments, unresolvable tool/version, inability to find or write a .tool-versions file, or permission errors when setting the version.","commonSituations":"Running `asdf set` in a directory where no .tool-versions exists and creation fails; specifying a tool with no plugin installed; typos in version strings; read-only or permission-restricted config files.","solutions":["Read the stderr message printed by the command — it names the specific problem","Verify the tool/plugin and version exist (`asdf plugin list`, `asdf list <tool>`) before running `asdf set`","Check write permissions on the .tool-versions file / directory you are setting the version in"],"exampleFix":"// before\n$ asdf set nodejs 99.9   # version never installed\n// after\n$ asdf install nodejs 20.12.0 && asdf set nodejs 20.12.0","handlingStrategy":"try-catch","validationCode":"// Go caller of the set command path\nif tool == \"\" || version == \"\" {\n    return fmt.Errorf(\"asdf set requires <tool> <version>\")\n}\nif _, err := os.Stat(filepath.Join(dir, \".tool-versions\")); err != nil {\n    // decide whether creating it is intended\n}","typeGuard":null,"tryCatchPattern":"if err := setCmd(args); err != nil {\n    // err text is the same message written to stderr; surface it to the user\n    fmt.Fprintf(os.Stderr, \"asdf set failed: %v\\n\", err)\n}","preventionTips":["Confirm the plugin and version are installed before `asdf set`","Ensure the working directory is writable and .tool-versions is not read-only","Inspect the stderr message — printError's text names the exact failing condition"],"tags":["cli","set","dynamic-error"],"backgroundTag":"asdf-set-failed","analyzedSha":"074a1722ca88d6677f228541ce06efaf4f9924d4","analyzedAt":"2026-08-30T19:56:42.972Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}