{"record":{"id":"1c923f59e839f025","repo":"kubernetes/kops","slug":"parsing-configstore-base-q-w","errorCode":null,"errorMessage":"parsing configStore.base %q: %w","messagePattern":"parsing configStore\\.base %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/commands/toolbox_enroll.go","lineNumber":940,"sourceCode":"\n\t\t\t*pSrc = dest\n\t\t\treturn nil\n\t\t}\n\n\t\tfor i := range nodeupConfig.EtcdManifests {\n\t\t\tif err := remapFile(&nodeupConfig.EtcdManifests[i], path.Join(targetDir)); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t}\n\n\t\t// The kops-channels static pod is built at cloudup with the remote bootstrap URL baked\n\t\t// into its args. To run on an enrolled node without state-store credentials, copy the\n\t\t// addons tree onto the host, pull the manifest down, then rewrite the bootstrap URL in\n\t\t// the manifest to file://<local addons>/bootstrap-channel.yaml (+ matching hostPath mount).\n\t\tif strings.HasPrefix(nodeupConfig.ChannelsManifest, remapPrefix) {\n\t\t\tconfigBase, err := vfs.Context.BuildVfsPath(cluster.Spec.ConfigStore.Base)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"parsing configStore.base %q: %w\", cluster.Spec.ConfigStore.Base, err)\n\t\t\t}\n\t\t\tbootstrapChannelURL := configBase.Join(\"addons\", \"bootstrap-channel.yaml\").Path()\n\n\t\t\taddonsPath := configBase.Join(\"addons\").Path()\n\t\t\tif err := remapTree(&addonsPath, path.Join(targetDir, \"addons\")); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tlocalAddons := addonsPath // remapTree mutated it in place to the on-host destination\n\t\t\tif err := remapFile(&nodeupConfig.ChannelsManifest, targetDir); err != nil {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\trewritten, err := rewriteChannelsManifestForEnroll(\n\t\t\t\tbootstrapData.NodeupScriptAdditionalFiles[nodeupConfig.ChannelsManifest],\n\t\t\t\tbootstrapChannelURL,\n\t\t\t\tlocalAddons,\n\t\t\t)\n\t\t\tif err != nil {\n\t\t\t\treturn nil, fmt.Errorf(\"rewriting channels manifest: %w\", err)","sourceCodeStart":922,"sourceCodeEnd":958,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/commands/toolbox_enroll.go#L922-L958","documentation":"When the channels manifest comes from s3, GetBootstrapData needs a vfs handle to the cluster's ConfigStore.Base to locate the addons/bootstrap-channel.yaml object. This error wraps a failure of vfs.Context.BuildVfsPath on cluster.Spec.ConfigStore.Base, i.e. the configured base string could not be parsed/validated as a VFS path.","triggerScenarios":"GetBootstrapData (called by getNodeConfig, RunToolboxEnroll, buildBootstrapData) on a control-plane group with an s3:// ChannelsManifest, where cluster.Spec.ConfigStore.Base is empty, malformed (bad scheme, unescaped characters, double slashes), or names a backend whose driver failed to initialize (missing region/bucket config).","commonSituations":"Cluster spec edited by hand or by tooling with an invalid configStore.base; migrating between state-store backends and leaving a stale URI; missing AWS region/env config so the s3 vfs context cannot resolve the bucket; typo'd scheme like s3a:// or file path used where a state-store URI is required.","solutions":["Inspect cluster.Spec.ConfigStore.Base (kops get cluster -o yaml) and fix it to a valid state-store URI, e.g. s3://<bucket>/<cluster>.","Ensure the backend context is complete: set the AWS region/credentials or GCS env so vfs can resolve the bucket.","If the field is empty, run `kops set cluster cluster.spec.configStore.base=s3://...` or update the cluster spec from a good export.","Validate the URI characters (no spaces/unescaped specials) and re-run toolbox enroll."],"exampleFix":"// before (malformed base in cluster spec)\nconfigStore:\n  base: \"s3://my bucket//cluster/\"\n// after\nconfigStore:\n  base: \"s3://my-bucket/cluster.example.com\"","handlingStrategy":"validation","validationCode":"// Before enroll: sanity-check the cluster's configStore.base\nspec=$(kops get cluster -o yaml | yq '.spec.configStore.base')\ncase \"$spec\" in\n  s3://*|gs://*) echo \"base OK: $spec\" ;;\n  *) echo \"INVALID base: $spec\"; exit 1 ;;\nesac","typeGuard":"func isValidStateStoreBase(base string) bool {\n    u, err := url.Parse(base)\n    return err == nil && (u.Scheme == \"s3\" || u.Scheme == \"gs\") && u.Host != \"\"\n}","tryCatchPattern":"if err := runToolboxEnroll(ctx, ...); err != nil {\n    if strings.Contains(err.Error(), \"parsing configStore.base\") {\n        // fix the spec then retry once\n        exec.Command(\"kops\", \"set\", \"cluster\", \"cluster.spec.configStore.base=s3://bucket/cluster\").Run()\n        return runToolboxEnroll(ctx, ...)\n    }\n    return err\n}","preventionTips":["Never hand-edit configStore.base; use `kops set cluster` / `kops edit cluster` and validate output.","Ensure backend env (AWS region, GCS project) is set before running any kops command.","After a state-store migration, always `kops get cluster -o yaml` to confirm the new base URI."],"tags":["go","vfs","config","state-store","path-parsing"],"backgroundTag":"invalid-state-store-uri","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}