GoogleContainerTools/skaffold · error
resource found in %s is not a k8s job, verify the manifest p
Error message
resource found in %s is not a k8s job, verify the manifest path is for a job resource
What it means
LoadFromPath decodes the manifest and inspects its group/version/kind; this error is thrown when the resource is valid YAML but is not a batch/v1 Job. The k8sjob package only processes Jobs, so any other kind (Pod, Deployment, CronJob, wrong API version) is rejected with an explicit hint to check the manifest path.
Source
Thrown at pkg/skaffold/k8sjob/util.go:103
if len(resourceYAML) == 0 {
return nil, fmt.Errorf("empty file found at path: %s, verify that the manifest path is correct", path)
}
// - obj is the API object (e.g., Job)
// - groupVersionKind is a generic object that allows
// detecting the API type we are dealing with, for
// accurate type casting later.
obj, groupVersionKind, err := decoder.Decode(
[]byte(resourceYAML),
nil,
nil)
if err != nil {
return nil, err
}
// Only process Jobs for now
if groupVersionKind.Group != "batch" || groupVersionKind.Version != "v1" || groupVersionKind.Kind != "Job" {
return nil, fmt.Errorf("resource found in %s is not a k8s job, verify the manifest path is for a job resource", path)
}
job := obj.(*batchv1.Job)
if job.Labels == nil {
job.Labels = map[string]string{}
}
return job, nil
}
func GetGenericJob() *batchv1.Job {
return &batchv1.Job{
TypeMeta: metav1.TypeMeta{
Kind: "Job",
APIVersion: "batch/v1",
},
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{},View on GitHub (pinned to a1189de023)
Solutions
- Open the file at the configured path and confirm the first/top-level resource is apiVersion: batch/v1 with kind: Job
- Fix the manifest path in the config to point at the actual Job manifest
- Update old manifests from batch/v1beta1 to batch/v1 for Job/CronJob kinds
- If the file has multiple documents, split them so the Job is the resource loaded
Example fix
// before apiVersion: batch/v1beta1 kind: CronJob // after apiVersion: batch/v1 kind: Job
Defensive patterns
Strategy: validation
Validate before calling
var meta metav1.TypeMeta
if err := yaml.Unmarshal(b, &meta); err != nil {
return err
}
if meta.GroupVersionKind().Group != "batch" || meta.GroupVersionKind().Kind != "Job" {
return fmt.Errorf("%s: expected batch/v1 Job, got %s", path, meta.GroupVersionKind())
} Type guard
func isBatchV1Job(gvk schema.GroupVersionKind) bool {
return gvk.Group == "batch" && gvk.Version == "v1" && gvk.Kind == "Job"
} Try / catch
job, err := k8sjob.LoadFromPath(path)
if err != nil {
if strings.Contains(err.Error(), "not a k8s job") {
return fmt.Errorf("manifest %q must be a batch/v1 Job", path)
}
return err
} Prevention
- Keep Job manifests in dedicated files separate from other resources
- Convert legacy batch/v1beta1 resources to batch/v1
- Run `kubectl apply --dry-run=client -f <file>` to confirm the parsed kind before use
- For multi-doc files, split documents so each file holds one Job
When it happens
Trigger: LoadFromPath is given a manifest whose groupVersionKind is not exactly group=batch, version=v1, kind=Job — e.g. the file contains a Pod, a Deployment, a batch/v1beta1 CronJob, or a multi-doc file whose first doc is another kind.
Common situations: Pointing the k8s job logging config at the deployment manifest instead of the job manifest, using an old apiVersion like batch/v1beta1, or a manifest file that starts with a ConfigMap before the Job document.
Related errors
- empty file found at path: %s, verify that the manifest path
- found existing node affinity for os/arch: %s
- unmarshaling config: %w
- collecting namespaces: %w
- error converting %s to map[string]interface{}
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/7b95d9013d0b9bf2.
Report an issue: GitHub.