{"record":{"id":"9c61c4a11138e3a4","repo":"kubernetes/kops","slug":"cachedir-is-required","errorCode":null,"errorMessage":"CacheDir is required","messagePattern":"CacheDir is required","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/nodeup/command.go","lineNumber":104,"sourceCode":"\tctx := context.Background()\n\n\tvar bootConfig nodeup.BootConfig\n\tif c.ConfigLocation != \"\" {\n\t\tb, err := vfs.Context.ReadFile(c.ConfigLocation)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error loading configuration %q: %v\", c.ConfigLocation, err)\n\t\t}\n\n\t\terr = utils.YamlUnmarshal(b, &bootConfig)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"error parsing configuration %q: %v\", c.ConfigLocation, err)\n\t\t}\n\t} else {\n\t\treturn fmt.Errorf(\"ConfigLocation is required\")\n\t}\n\n\tif c.CacheDir == \"\" {\n\t\treturn fmt.Errorf(\"CacheDir is required\")\n\t}\n\n\tregion, err := getRegion(ctx, &bootConfig)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\tvar configBase vfs.Path\n\n\t// If we're using a config server instead of vfs, nodeConfig will hold our configuration\n\tvar nodeConfig *nodeup.NodeConfig\n\n\tif bootConfig.ConfigServer != nil && len(bootConfig.ConfigServer.Servers) > 0 {\n\t\tresponse, err := getNodeConfigFromServers(ctx, &bootConfig, region)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed to get node config from server: %w\", err)\n\t\t}\n\t\tnodeConfig = response.NodeConfig","sourceCodeStart":86,"sourceCodeEnd":122,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/nodeup/command.go#L86-L122","documentation":"NodeUpCommand requires CacheDir, the local directory where nodeup caches downloaded binaries and assets. Run returns this error immediately when the field is empty. It is a required-flag/usage error; nodeup does not infer a default cache directory.","triggerScenarios":"Invoking nodeup without --cachedir, or constructing NodeUpCommand in code without setting CacheDir.","commonSituations":"Systemd unit or user-data template missing the --cachedir argument; custom code building NodeUpCommand but leaving CacheDir empty; regression in generated nodeup invocation.","solutions":["Pass --cachedir /var/cache/nodeup (or equivalent writable path) when invoking nodeup","Set NodeUpCommand.CacheDir in code before calling Run","Ensure the generated user-data/unit file includes the cachedir argument and the path exists and is writable by root"],"exampleFix":"// before\nnodeup --config s3://bucket/... (no --cachedir)\n// after\nnodeup --config s3://bucket/... --cachedir /var/cache/nodeup","handlingStrategy":"validation","validationCode":"if cfg.CacheDir == \"\" {\n  return errors.New(\"nodeup requires --cachedir (e.g. /var/cache/nodeup)\")\n}","typeGuard":"func cacheReady(cmd *NodeUpCommand) bool { return cmd.CacheDir != \"\" }","tryCatchPattern":"if err := cmd.Run(os.Stdout); err != nil {\n  if err.Error() == \"CacheDir is required\" {\n    klog.Error(\"nodeup invoked without --cachedir; fix the user-data/systemd unit\")\n    os.Exit(2)\n  }\n  return err\n}","preventionTips":["Always pass --cachedir /var/cache/nodeup in nodeup templates","Ensure the cache directory exists and is writable before invoking nodeup","Include both required flags (--config, --cachedir) in a shared launch template snippet reused across clusters"],"tags":["nodeup","configuration","missing-argument"],"backgroundTag":"missing-required-flag","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}