{"record":{"id":"ecf2ddaa6a5f6e86","repo":"kubernetes/kops","slug":"assetslocation-filerepository-must-be-set-to-remap","errorCode":null,"errorMessage":"assetsLocation.fileRepository must be set to remap asset %v","messagePattern":"assetsLocation\\.fileRepository must be set to remap asset (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/assets/builder.go","lineNumber":453,"sourceCode":"\t\t\tif ext == \".sha256\" {\n\t\t\t\tklog.V(2).Infof(\"Unable to read new sha256 hash file (is this an older/unsupported kubernetes release?)\")\n\t\t\t}\n\t\t}\n\t}\n\n\tif a.assetsLocation != nil && a.assetsLocation.FileRepository != nil {\n\t\treturn nil, fmt.Errorf(\"you might have not staged your files correctly, please execute 'kops get assets --copy'\")\n\t}\n\treturn nil, fmt.Errorf(\"cannot determine hash for %q (have you specified a valid file location?)\", u)\n}\n\nfunc (a *AssetBuilder) remapURL(canonicalURL *url.URL) (*url.URL, error) {\n\tf := \"\"\n\tif a.assetsLocation != nil {\n\t\tf = values.StringValue(a.assetsLocation.FileRepository)\n\t}\n\tif f == \"\" {\n\t\treturn nil, fmt.Errorf(\"assetsLocation.fileRepository must be set to remap asset %v\", canonicalURL)\n\t}\n\n\tfileRepo, err := url.Parse(f)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"unable to parse assetsLocation.fileRepository %q: %v\", f, err)\n\t}\n\n\tfileRepo.Path = path.Join(fileRepo.Path, canonicalURL.Path)\n\t// Escape commas, which are legal in a path but separate locations in CompactString.\n\tfileRepo.RawPath = strings.ReplaceAll(fileRepo.EscapedPath(), \",\", \"%2C\")\n\n\treturn fileRepo, nil\n}\n\nfunc NormalizeImage(a *AssetBuilder, image string) string {\n\tif a.assetsLocation != nil && a.assetsLocation.ContainerProxy != nil {\n\t\tcontainerProxy := strings.TrimSuffix(*a.assetsLocation.ContainerProxy, \"/\")\n\t\tnormalized := image","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/pkg/assets/builder.go#L435-L471","documentation":"AssetBuilder.remapURL rewrites canonical kops asset URLs to point at a user-configured file repository (a mirror of kops assets). Before remapping, it reads assetsLocation.fileRepository; if it is empty or assetsLocation is nil, it cannot construct the mirrored URL, so it fails with this error. It guards against silently emitting a half-remapped or unchanged asset URL.","triggerScenarios":"Calling AssetBuilder.RemapFile (via Build) while AssetsLocation is nil, or AssetsLocation is set with an empty/unset FileRepository field (e.g. Cluster.Spec.AssetsLocation with only containerRegistry set).","commonSituations":"Users set cluster.spec.assetsLocation.containerRegistry to mirror container images but forget fileRepository, which is separately required to mirror the nodeup/protokube/cni binary assets; or assetsLocation is partially populated by an older cluster spec.","solutions":["Set cluster.spec.assetsLocation.fileRepository to a valid base URL (e.g. https://artifacts.example.com/kops) and update the cluster (kops update cluster).","If you only wanted container image mirroring, ensure fileRepository is still set or remove assetsLocation entirely so assets use default URLs.","Verify with kops get cluster --yaml that assetsLocation.fileRepository is non-empty before running kops update/replace."],"exampleFix":"// before (cluster spec)\nassetsLocation:\n  containerRegistry: registry.example.com/kops\n// after\nassetsLocation:\n  containerRegistry: registry.example.com/kops\n  fileRepository: https://artifacts.example.com/kops","handlingStrategy":"validation","validationCode":"if a.AssetsLocation == nil || values.StringValue(a.AssetsLocation.FileRepository) == \"\" {\n    return fmt.Errorf(\"assetsLocation.fileRepository must be set before RemapFile\")\n}","typeGuard":"func hasFileRepository(al *kops.AssetsLocation) bool {\n    return al != nil && al.FileRepository != nil && *al.FileRepository != \"\"\n}","tryCatchPattern":"u, err := builder.RemapFile(canonicalURL)\nif err != nil {\n    var cfgErr *ConfigFieldError\n    if errors.As(err, &cfgErr) && strings.Contains(err.Error(), \"fileRepository must be set\") {\n        // prompt for/repair assetsLocation.fileRepository\n    }\n    return err\n}","preventionTips":["Always set both containerRegistry and fileRepository together when configuring assetsLocation.","Validate the cluster spec with kops get cluster -o yaml before kops update.","Add a CI check asserting spec.assetsLocation.fileRepository is a non-empty URL when assetsLocation is present."],"tags":["go","assets","configuration","kops"],"backgroundTag":"missing-config-field","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"}