{"record":{"id":"12f52c3da569087a","repo":"GoogleContainerTools/skaffold","slug":"pre-sync-hooks-failed-for-artifact-q-w","errorCode":null,"errorMessage":"pre-sync hooks failed for artifact %q: %w","messagePattern":"pre-sync hooks failed for artifact %q: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/skaffold/sync/sync.go","lineNumber":295,"sourceCode":"\tif !item.HasChanges() {\n\t\treturn nil\n\t}\n\n\tvar copy, delete []string\n\tfor k := range item.Copy {\n\t\tcopy = append(copy, k)\n\t}\n\tfor k := range item.Delete {\n\t\tdelete = append(delete, k)\n\t}\n\n\topts, err := hooks.NewSyncEnvOpts(item.Artifact, item.Image, copy, delete, *s.namespaces, s.kubectl.KubeContext)\n\tif err != nil {\n\t\treturn err\n\t}\n\thooksRunner := hooks.NewSyncRunner(s.kubectl, item.Artifact.ImageName, item.Image, *s.namespaces, s.formatter, item.Artifact.Sync.LifecycleHooks, opts)\n\tif err := hooksRunner.RunPreHooks(ctx, out); err != nil {\n\t\treturn fmt.Errorf(\"pre-sync hooks failed for artifact %q: %w\", item.Artifact.ImageName, err)\n\t}\n\tif err := s.sync(ctx, item); err != nil {\n\t\treturn err\n\t}\n\tif err := hooksRunner.RunPostHooks(ctx, out); err != nil {\n\t\treturn fmt.Errorf(\"post-sync hooks failed for artifact %q: %w\", item.Artifact.ImageName, err)\n\t}\n\treturn nil\n}\n\nfunc (s *PodSyncer) sync(ctx context.Context, item *Item) error {\n\tif len(item.Copy) > 0 {\n\t\tlog.Entry(ctx).Info(\"Copying files:\", item.Copy, \"to\", item.Image)\n\n\t\tif err := Perform(ctx, item.Image, item.Copy, s.copyFileFn, *s.namespaces, s.kubectl.KubeContext); err != nil {\n\t\t\treturn fmt.Errorf(\"copying files: %w\", err)\n\t\t}\n\t}","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/GoogleContainerTools/skaffold/blob/a1189de023efc32d4b8e11f395acc678aa555011/pkg/skaffold/sync/sync.go#L277-L313","documentation":"The PodSyncer.Sync entry point runs the artifact's pre-sync lifecycle hooks (kubectl-based) before performing the copy/delete sync. If RunPreHooks fails, Skaffold wraps the error naming the artifact image so users know which artifact's hooks failed.","triggerScenarios":"Any `sync.lifecycleHooks.preSync` exec or container hook returns non-zero, times out, or errors creating the hook environment (bad kube context, missing namespace, invalid hook spec) during a sync triggered by file change.","commonSituations":"preSync exec command references a binary absent in the container image; hook pod targets a namespace that doesn't exist; kube context switched to a cluster where the pod isn't running; container hook times out on slow startup.","solutions":["Check the nested error's output: run the failing hook's command manually (kubectl exec) in the target pod/namespace","Fix the preSync spec in skaffold.yaml (command, container name, timeouts) for the artifact named in the message","Verify *s.namespaces and the kube context match where the app actually runs (kubectl config current-context)"],"exampleFix":"// before\nsync:\n  lifecycleHooks:\n    preSync:\n      - exec: {command: [\"./scripts/missing.sh\"]}\n// after\nsync:\n  lifecycleHooks:\n    preSync:\n      - exec: {command: [\"sh\", \"-c\", \"curl -fs http://localhost:8080/health\"]}","handlingStrategy":"try-catch","validationCode":"for _, h := range a.Sync.LifecycleHooks.PreSync {\n    if h.Exec != nil && len(h.Exec.Command) == 0 { return errors.New(\"empty preSync exec command\") }\n    if h.Container != nil && h.Container.ContainerName == \"\" { return errors.New(\"preSync container hook missing containerName\") }\n}\n// also verify pod/namespace exist: kubectl get ns <ns>","typeGuard":null,"tryCatchPattern":"err := s.Sync(ctx, out, names, item)\nif err != nil {\n    var hookErr interface{ Unwrap() error }\n    if errors.As(err, &hookErr) && strings.Contains(err.Error(), \"pre-sync hooks failed\") {\n        log.Errorf(\"artifact %s preSync failed, continuing sync state check: %v\", item.Artifact.ImageName, err)\n    }\n    return err\n}","preventionTips":["Test lifecycle hook commands manually in the target pod before adding them to skaffold.yaml","Pin hook container names to ones guaranteed present in the pod spec","Set explicit timeouts and make hooks idempotent so retries are safe"],"tags":["skaffold","sync","hooks","kubectl"],"backgroundTag":"sync-hook-failed","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"}