DevFlow logoDevFlow
Developer Tools
~6 min read
All Guides

Kubernetes YAML Validation: The 10 Most Common Manifest Mistakes

Diagnose and fix syntax errors, missing resource limits, selector mismatches, and schema validation failures in Kubernetes manifests before deployment.

Primary Interactive Tool:/tools/k8s-yaml-validator

Kubernetes manifests define the declarative desired state of containerized workloads, ingress routing, and cloud infrastructure. However, because YAML relies entirely on whitespace indentation and implicit type coercion, subtle syntax flaws and schema mismatches frequently slip through peer reviews, crashing CI/CD pipelines and causing cluster downtime.

This guide details the 10 most common Kubernetes YAML validation errors, their root causes, and how to fix them before running kubectl apply.


1. The "Norway Problem" (Unquoted Booleans and Country Codes)

In the YAML 1.1 specification (which many Kubernetes parsers still use), unquoted strings like NO, no, YES, yes, ON, off, TRUE, and false are automatically coerced into boolean values.

  • The Bug: Defining COUNTRY_CODE: NO (for Norway) results in COUNTRY_CODE: false.
  • The Fix: Always wrap string values that resemble booleans or country codes in double quotes:
env:
  - name: COUNTRY_CODE
    value: "NO" # ✅ Correct: explicitly quoted string
  - name: FEATURE_FLAG_ENABLED
    value: "true"

2. Label Selector (matchLabels) and Pod Template Metadata Mismatch

In Deployment, StatefulSet, and DaemonSet controllers, the spec.selector.matchLabels key must exactly match the labels specified inside spec.template.metadata.labels.

  • The Bug: If the labels differ by even a single character, kubectl apply will fail with The Deployment "api" is invalid: spec.template.metadata.labels: Invalid value: mapping[string]string....
  • The Fix: Ensure identical label key-value mappings:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-service
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: api-service # ⚠️ Must match template labels below
  template:
    metadata:
      labels:
        app.kubernetes.io/name: api-service # ✅ Exact match

3. Missing CPU & Memory Requests and Limits

Omitting container resource configurations causes the Kubernetes scheduler to treat pods as "BestEffort" Quality of Service (QoS). Under node memory pressure, these pods are the first to be terminated (OOMKilled).

  • The Fix: Always specify explicit requests (for scheduling) and limits (for containment):
resources:
  requests:
    cpu: "250m" # 0.25 vCPU cores
    memory: "256Mi"
  limits:
    cpu: "1000m" # 1.0 vCPU core
    memory: "512Mi"

4. Port Number vs. Port Name Type Clashes

In a Kubernetes Service, targetPort can accept either an integer port number (e.g. 8080) or an alphanumeric string matching a named containerPort in the Pod spec.

  • The Bug: Quoting a numeric port (targetPort: "8080") causes Kubernetes to look for a named port literally called "8080" rather than port number 8080.
  • The Fix: Use raw integers for port numbers, or named strings that match container definitions:
apiVersion: v1
kind: Service
metadata:
  name: web-svc
spec:
  ports:
    - name: http
      port: 80
      targetPort: 8080 # ✅ Integer for port numbers, or string for named ports

5. Tab Indentation Violations & Document Delimiters

YAML strictly prohibits the ASCII tab character (\t) for indentation. A single stray tab copied from an IDE or webpage triggers: error: error converting YAML to JSON: yaml: line X: found character that cannot start any token

  • The Fix: Configure your editor to convert tabs to 2 spaces. When bundling multiple resources in one file, separate them cleanly using triple dashes (---).

6. Unquoted Numbers and Booleans in ConfigMaps & Annotations

Kubernetes metadata.annotations and ConfigMap.data fields require all values to be strings.

  • The Bug: Writing version: 1.0 or active: true results in schema rejection: got "number", expected "string".
  • The Fix: Explicitly quote numbers, floats, and boolean values in ConfigMaps:
apiVersion: v1
kind: ConfigMap
metadata:
  name: app-config
data:
  API_VERSION: "1.0" # ✅ Must be quoted
  MAX_RETRIES: "5"

7. Missing Liveness and Readiness Probes

Without readiness probes, Kubernetes sends traffic to freshly created pods before your application framework or database connection pool has initialized, resulting in 502 Bad Gateway errors during rolling updates.

  • The Fix: Define health check probes:
livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 15
  periodSeconds: 20
readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 5
  periodSeconds: 10

8. Default ServiceAccount & Missing Least Privilege

By default, pods mount the namespace's default ServiceAccount credentials. If unauthorized users or attackers compromise a container, they inherit access to the Kubernetes API.

  • The Fix: Disable automatic API token mounting if the container does not query the cluster API:
spec:
  automountServiceAccountToken: false
  containers:
    - name: web
      image: registry.example.com/app:v1.2.0

9. Implicit latest Image Tag & Missing imagePullPolicy

Using the latest image tag or omitting tags entirely defaults imagePullPolicy to Always. This causes non-deterministic deployments and cache invalidation bottlenecks.

  • The Fix: Always use explicit semantic version tags or immutable image digest hashes (e.g. image: myapp:v1.4.2 or myapp@sha256:...) with imagePullPolicy: IfNotPresent.

10. Attempting to Mutate Immutable Spec Fields

Certain fields in Kubernetes resources cannot be modified in-place after initial creation (such as spec.clusterIP in Services or spec.selector in Deployments).

  • The Bug: The Deployment "api" is invalid: spec.selector: Invalid value: ... field is immutable.
  • The Fix: To modify immutable fields, delete and re-create the resource or perform a rolling deployment under a new name.

Validating Manifests in Your Workflow


Frequently Asked Questions

How do I validate Kubernetes YAML manifests without a running cluster?

You can validate Kubernetes YAML offline by checking schemas against official JSONSchema definitions using the DevFlow Kubernetes YAML Validator or running kubectl apply --dry-run=client -f manifest.yaml.

Why does kubectl reject tabs in YAML configuration files?

The YAML specification disallows tab characters for indentation because different operating systems and text editors render tab stops with varying column widths, leading to ambiguous document hierarchies.

What is the difference between kubectl --dry-run=client and --dry-run=server?

Client-side dry run (--dry-run=client) verifies basic syntax and local schema structure without connecting to the API server. Server-side dry run (--dry-run=server) transmits the manifest to the Kubernetes master node to run admission controllers, schema validations, and permission checks without persisting changes to etcd.

Interactive Tools for this Guide

Free, browser-based utilities to test, validate, and inspect workflows related to “Kubernetes YAML Validation: The 10 Most Common Manifest Mistakes”.

100% Client-Side • No Setup