{"record":{"id":"b6701ea0b0c69a99","repo":"GoogleContainerTools/skaffold","slug":"sync-rule-pattern-s-does-not-have-prefix-s","errorCode":null,"errorMessage":"sync rule pattern '%s' does not have prefix '%s'","messagePattern":"sync rule pattern '(.+?)' does not have prefix '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/schema/validation/validation.go","lineNumber":559,"sourceCode":"\t\tif v.IsNil() {\n\t\t\treturn nil\n\t\t}\n\t\treturn visitStructs(cfg, v.Elem(), visitor)\n\n\tdefault:\n\t\t// other values are fine\n\t\treturn nil\n\t}\n}\n\n// validateSyncRules checks that all manual sync rules have a valid strip prefix\nfunc validateSyncRules(cfg *parser.SkaffoldConfigEntry, artifacts []*latest.Artifact) []ErrorWithLocation {\n\tvar cfgErrs []ErrorWithLocation\n\tfor i, a := range artifacts {\n\t\tif a.Sync != nil {\n\t\t\tfor _, r := range a.Sync.Manual {\n\t\t\t\tif !strings.HasPrefix(r.Src, r.Strip) {\n\t\t\t\t\terr := fmt.Errorf(\"sync rule pattern '%s' does not have prefix '%s'\", r.Src, r.Strip)\n\t\t\t\t\tcfgErrs = append(cfgErrs, ErrorWithLocation{\n\t\t\t\t\t\tError:    err,\n\t\t\t\t\t\tLocation: cfg.YAMLInfos.LocateField(cfg.Build.Artifacts[i], \"Sync\"),\n\t\t\t\t\t})\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn cfgErrs\n}\n\n// validatePortForwardResources checks that all user defined port forward resources\n// have a valid resourceType\nfunc validatePortForwardResources(cfg *parser.SkaffoldConfigEntry, pfrs []*latest.PortForwardResource) []ErrorWithLocation {\n\tvar errs []ErrorWithLocation\n\tvalidResourceTypes := map[string]struct{}{\n\t\t\"container\":             {},\n\t\t\"pod\":                   {},","sourceCodeStart":541,"sourceCodeEnd":577,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/schema/validation/validation.go#L541-L577","documentation":"validateSyncRules checks manual sync rules: each rule's Src file pattern must start with its Strip prefix, since Strip removes that prefix from the source path before mapping to the container. If Src doesn't begin with Strip, the mapping is nonsensical and validation fails.","triggerScenarios":"An artifact's sync.manual rule has a strip value that is not a prefix of src, e.g. src: 'src/**/*.js' with strip: 'dist/', detected via strings.HasPrefix(r.Src, r.Strip).","commonSituations":"Copy-pasting sync rules from another project and editing src but not strip, or setting strip to the container-side path instead of the host-side prefix.","solutions":["Make strip a genuine prefix of src, e.g. src: 'src/app/**' with strip: 'src/'","Set strip to '' if you don't need prefix stripping","Verify each manual rule maps host paths under Src to the container path after removing Strip"],"exampleFix":"// before\nsync:\n  manual:\n    - src: 'src/**/*.js'\n      strip: 'dist/'\n// after\nsync:\n  manual:\n    - src: 'src/**/*.js'\n      strip: 'src/'","handlingStrategy":"validation","validationCode":"// Go: each sync rule's strip must be a prefix of src\nfunc validSyncRule(src, strip string) bool { return strings.HasPrefix(src, strip) }","typeGuard":null,"tryCatchPattern":"if !validSyncRule(rule.Src, rule.Strip) {\n\treturn fmt.Errorf(\"sync rule src %q must start with strip %q\", rule.Src, rule.Strip)\n}","preventionTips":["Set strip to the host-side directory prefix shared with src, never the container path","Omit strip when no prefix stripping is needed","Re-check sync rules after moving or renaming source directories"],"tags":["skaffold","file-sync","sync-rules","config-validation"],"backgroundTag":"invalid-sync-rule-prefix","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"}