{"record":{"id":"be5d30e2a36ef7a9","repo":"GoogleContainerTools/skaffold","slug":"artifact-s-cannot-use-inferred-file-sync-when-the","errorCode":null,"errorMessage":"artifact %s cannot use inferred file sync when the ko.main field contains the '...' wildcard. Instead, specify the path to the main package without using wildcards","messagePattern":"artifact (.+?) cannot use inferred file sync when the ko\\.main field contains the '\\.\\.\\.' wildcard\\. Instead, specify the path to the main package without using wildcards","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/schema/validation/validation.go","lineNumber":626,"sourceCode":"\t\t}\n\t\tcfgErrs = append(cfgErrs, ErrorWithLocation{\n\t\t\tError:    fmt.Errorf(\"artifact %s has invalid Jib plugin type '%s'\", a.ImageName, t),\n\t\t\tLocation: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].JibArtifact, \"Type\"),\n\t\t})\n\t}\n\treturn\n}\n\n// validateKoSync ensures that infer sync patterns contain the `kodata` string, since infer sync for the ko builder only supports static assets.\nfunc validateKoSync(cfg *parser.SkaffoldConfigEntry, artifacts []*latest.Artifact) []ErrorWithLocation {\n\tvar cfgErrs []ErrorWithLocation\n\tfor i, a := range artifacts {\n\t\tif a.KoArtifact == nil || a.Sync == nil {\n\t\t\tcontinue\n\t\t}\n\t\tif len(a.Sync.Infer) > 0 && strings.Contains(a.KoArtifact.Main, \"...\") {\n\t\t\tcfgErrs = append(cfgErrs, ErrorWithLocation{\n\t\t\t\tError:    fmt.Errorf(\"artifact %s cannot use inferred file sync when the ko.main field contains the '...' wildcard. Instead, specify the path to the main package without using wildcards\", a.ImageName),\n\t\t\t\tLocation: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].KoArtifact, \"Main\"),\n\t\t\t})\n\t\t}\n\t\tfor _, pattern := range a.Sync.Infer {\n\t\t\tif !strings.Contains(pattern, \"kodata\") {\n\t\t\t\tcfgErrs = append(cfgErrs, ErrorWithLocation{\n\t\t\t\t\tError:    fmt.Errorf(\"artifact %s has an invalid pattern %s for inferred file sync with the ko builder. The pattern must specify the 'kodata' directory. For instance, if you want to sync all static content, and your main package is in the workspace directory, you can use the pattern 'kodata/**/*'\", a.ImageName, pattern),\n\t\t\t\t\tLocation: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i].Sync, \"Infer\"),\n\t\t\t\t})\n\t\t\t}\n\t\t}\n\t}\n\treturn cfgErrs\n}\n\n// validateArtifactTypes checks that the artifact types are compatible with the specified builder.\nfunc validateArtifactTypes(cfg *parser.SkaffoldConfigEntry, bc latest.BuildConfig) []ErrorWithLocation {\n\tcfgErrs := []ErrorWithLocation{}","sourceCodeStart":608,"sourceCodeEnd":644,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/schema/validation/validation.go#L608-L644","documentation":"When a ko artifact uses inferred file sync (sync.infer), the ko.main field must be a concrete package path. If ko.main contains the Go wildcard '...' (e.g. ./...), Skaffold cannot resolve a single kodata root for inferred sync, so it rejects the combination and asks you to point at the main package directly.","triggerScenarios":"An artifact with ko: (ko.main containing '...'), a non-empty sync.infer list, processed via ProcessToErrorWithLocation -> validateKoSync.","commonSituations":"Users copy `main: ./...` from go build habits or module layout docs and then add sync.infer for hot-reload; the combination is unsupported.","solutions":["Change ko.main to the explicit path of the main package (e.g. `./cmd/server`) without '...'","Remove the sync.infer section if wildcard main is required","Use explicit sync manual/manual patterns instead of inferred sync"],"exampleFix":"# before\nbuild:\n  artifacts:\n    - image: myapp\n      ko:\n        main: ./...\n      sync:\n        infer:\n          - '**/*.go'\n# after\nbuild:\n  artifacts:\n    - image: myapp\n      ko:\n        main: ./cmd/myapp\n      sync:\n        infer:\n          - '**/*.go'","handlingStrategy":"validation","validationCode":"if (artifact.ko && artifact.sync?.infer?.length && String(artifact.ko.main || '').includes('...')) {\n  throw new Error(`artifact '${artifact.imageName}': sync.infer requires ko.main without '...' wildcard`);\n}","typeGuard":"function koSyncCompatible(a) {\n  return !(a?.ko && a?.sync?.infer?.length > 0 && String(a.ko.main ?? '').includes('...'));\n}","tryCatchPattern":"try {\n  await skaffold.dev();\n} catch (e) {\n  if (/cannot use inferred file sync/.test(e.message)) {\n    console.error('Point ko.main at the concrete main package path (no ...) or drop sync.infer');\n  } else throw e;\n}","preventionTips":["Always specify ko.main as an explicit package path (e.g. ./cmd/server)","Reserve ./... for go build/test commands, not skaffold ko.main","Prefer explicit sync.manual patterns when wildcard package paths are required"],"tags":["skaffold","config-validation","ko","file-sync"],"backgroundTag":"skaffold-config-validation","analyzedSha":"a1189de023efc32d4b8e11f395acc678aa555011","analyzedAt":"2026-09-05T12:09:27.064Z","contentChangedAt":"2026-09-05T12:09:27.064Z","schemaVersion":2},"datasetVersion":"2026-09-12T17:17:11.597Z"}