Troubleshooting

This page covers common failures during application development, submission, and deployment, and how to resolve each one.


Submission errors

"Invalid YAML format"

Cause: The uploaded Docker Compose file contains YAML syntax errors.

Fix: Run yamllint clv-docker-compose.yml locally and check for:

  • Tabs instead of spaces (YAML requires spaces)
  • Incorrect indentation (child keys must be indented more than their parents)
  • Missing quotes around values that contain special characters (:, #, {, })
  • Unclosed quotes or brackets
# Bad - tab indentation
services:
	wordpress:          # ← tab character
	  image: wordpress:6.7.1

# Good - space indentation
services:
  wordpress:
    image: wordpress:6.7.1

"No valid services found"

Cause: The YAML file doesn't have a services: section, or the section is empty.

Fix: Make sure the file has a valid services: block with at least one service:

version: "3.8"
services:       # ← must be present
  my-app:
    image: myapp:1.0.0
    ...

"Container name invalid"

Cause: A container name contains uppercase letters, underscores, or dots, or starts or ends with a hyphen.

Fix: Rename using only lowercase letters, numbers, and hyphens:

❌ MyApp_Backend → ✅ myapp-backend
❌ postgres.db   → ✅ postgres-db
❌ -web-app      → ✅ web-app
❌ api_service   → ✅ api-service

"Image tag must be specified"

Cause: An image uses the latest tag or no tag at all.

Fix: Specify an exact version tag:

# Bad
image: wordpress:latest
image: nginx

# Good
image: wordpress:6.7.1
image: nginx:1.27.3

"Missing x-clouve-metadata on service 'xyz'"

Cause: A service in the manifest doesn't have the required x-clouve-metadata block.

Fix: Add the block to every service:

services:
  my-service:
    image: my-image:1.0.0
    ...
    x-clouve-metadata:
      containerName: my-service
      purpose: Backend
      protocol: TCP
      isPublic: false
      memoryBase: 1 # 1 GB
      cpuBase: 0.5

"memoryBase must be a positive number ≥ 1"

Cause: memoryBase is set as a string, in megabytes (e.g., 512, intending Mi), or below the 1 GB minimum.

Fix: Use a decimal number of gibibytes (GB), minimum 1:

# Bad
memoryBase: "1"       # string not allowed
memoryBase: 512       # 512 GB: would be rejected anyway, and probably not what you meant
memoryBase: 0.5       # below the 1 GB minimum

# Good
memoryBase: 1         # 1 GB
memoryBase: 2         # 2 GB

"cpuBase must be ≥ 0.5"

Cause: cpuBase uses Kubernetes millicores notation (e.g., 500m) or is below the 0.5-core minimum.

Fix: Use decimal cores, minimum 0.5:

# Bad
cpuBase: "500m"   # millicores notation not supported
cpuBase: 0.25     # below the 0.5-core minimum

# Good
cpuBase: 0.5      # half a CPU core (minimum)
cpuBase: 1        # one full CPU core

"Volume size must include units" / "must be at least 8 Gi"

Cause: A volume size is specified without Gi or Mi, or is below the 8 Gi minimum.

Fix:

# Bad
size: 10           # bare numbers are interpreted as Gi but < 8 fails
size: 1Gi          # below the 8 Gi minimum
size: 4096Mi       # 4 Gi: below the 8 Gi minimum

# Good
size: 8Gi          # minimum allowed
size: 10Gi
size: 100Gi

Runtime and deployment errors

Container fails to start (CrashLoopBackOff)

The container starts, crashes right away, and Kubernetes restarts it repeatedly.

Diagnosis: Check the application logs in the deployment dashboard and look for error messages at startup.

Common causes:

CauseSignsFix
Missing required env var"Required environment variable X not set" in logsEnsure all required variables are declared and typed
Wrong database host"Connection refused" or "could not connect to server"Check containerReference variable points to correct container name
Database not ready on startup"ECONNREFUSED" immediately after startIncrease initialDelay, add retry logic in app
Wrong image"manifest unknown"Verify image name and tag are correct and accessible
Insufficient memoryOOMKilled in statusIncrease memoryBase

Health check keeps failing

The container is running but Kubernetes marks it as unhealthy and restarts it.

Diagnosis: Check what the health check is testing and whether it matches your application.

Common causes:

CauseFix
Health endpoint doesn't existCreate a /health endpoint that returns 200 OK
Wrong pathUpdate path in x-clouve-healthcheck to match actual endpoint
Wrong portUpdate port to match your container's listening port
App not ready in timeIncrease initialDelay
Health endpoint requires authRemove auth requirement from health endpoint
HTTP check on a TCP-only serviceChange type to TCP

Container can't connect to the database

Cause: The containerReference variable for the database hostname isn't set up correctly.

Diagnosis: Check that the env var value matches the database container name exactly:

# Application container
environment:
  DB_HOST: postgres-db # Must exactly match the database container name

x-clouve-environment-types:
  DB_HOST: containerReference

# Database container
services:
  postgres-db: # This name must match the value above exactly
    image: postgres:16

Common mistakes:

  • The value uses an underscore (postgres_db) but the container is named postgres-db
  • The value has the wrong capitalization (Postgres-DB instead of postgres-db)
  • The type: containerReference declaration is missing, so the value is treated as a static string instead of a resolved hostname

Application shows the wrong URL in generated links

Cause: The application's base URL variable is typed as static instead of applicationUrl.

Fix: Change the variable type to applicationUrl:

environment:
  SITE_URL: "" # Value will be replaced automatically

x-clouve-environment-types:
  SITE_URL: applicationUrl # ← not "static"

Volume data not persisting

Cause: The application writes data to a path inside the container that isn't mounted to a volume.

Diagnosis: Check that the mount path in volumes: matches the path your application actually writes to.

# Check your image documentation for the data directory
# PostgreSQL writes to /var/lib/postgresql/data
volumes:
  - postgres-data:/var/lib/postgresql/data   # Correct

# Common mistake: wrong path
volumes:
  - postgres-data:/data                       # Wrong: PostgreSQL won't find it here

"No services found after upload" on YAML upload

Cause: The file contains only comments, or the services: key is at the wrong indentation level.

Fix:

  1. Verify the file is valid Docker Compose YAML
  2. Check that services: is at the root level (no indentation)
  3. Verify at least one service has an image: field

Environment variables not imported correctly after upload

Cause: Variable names in x-clouve-environment-types don't exactly match the names in environment:.

Fix: Names must match exactly (case-sensitive):

environment:
  DATABASE_URL: postgres-db # Uppercase
  jwt_secret: changeme # Lowercase

x-clouve-environment-types:
  DATABASE_URL: containerReference # ✅ Matches
  jwt_secret: secret # ✅ Matches
  JWT_SECRET: secret # ❌ Wrong case: won't match jwt_secret

Health check state issues

Health check always shows as enabled after upload

Cause: The uploaded file has a missing or incorrectly formatted enabled field.

Fix: Include an explicit enabled: true or enabled: false:

# Correct
x-clouve-healthcheck:
  enabled: false    # ← explicit boolean
  type: HTTP
  ...

# Wrong: missing enabled field defaults to false
x-clouve-healthcheck:
  type: HTTP
  ...

# Wrong: string instead of boolean
x-clouve-healthcheck:
  enabled: "false"   # ← string, not boolean
  type: HTTP
  ...

Bundle-specific issues

"Bundle naming validation failed"

Cause: A private container doesn't follow the {mainApp}-{service} naming convention.

Fix: Rename the container to include the main app prefix:

❌ mariadb    → ✅ moodle-mariadb
❌ database   → ✅ wordpress-database
❌ redis      → ✅ myapp-redis

Wrong app on the default subdomain

Cause: The wrong container is first in the services list.

Fix: In the UI, drag the correct app's container tab to the first position. The first container becomes the primary app on the default subdomain.


Manifest generation errors

"Schema validation failed: missing field 'memoryBase'"

Cause: memoryBase is missing from x-clouve-metadata.

Fix: Add all required fields to every x-clouve-metadata block:

x-clouve-metadata:
  containerName: my-service # required
  purpose: Backend # required
  protocol: TCP # required
  isPublic: false # required
  memoryBase: 1 # required, GB (gibibytes), minimum 1
  cpuBase: 0.5 # required, decimal cores, minimum 0.5

Getting more help

If you've worked through this guide and are still stuck:

  1. Check the application logs. The most specific information is always in the container logs.
  2. Validate your YAML with yamllint clv-docker-compose.yml and docker-compose config.
  3. Test locally with docker-compose up to verify the app works outside the platform.
  4. Simplify: start with a single container, get it working, then add complexity.
  5. Check the platform logs. The deployment dashboard shows detailed error messages from manifest generation.

Quick diagnostic checklist

When something isn't working, run through this list:

  • YAML syntax is valid (yamllint passes)
  • All container names use lowercase + hyphens only
  • All images use specific version tags
  • Every container has all four x-clouve-* blocks
  • containerName in x-clouve-metadata matches the service key
  • memoryBase is in GB (gibibytes), minimum 1: 1 = 1 GB, 2 = 2 GB
  • cpuBase is in decimal cores, minimum 0.5
  • Volume names match between volumes:, x-clouve-volumes, and top-level volumes:
  • Volume sizes include units and are at least 8Gi
  • Database containers are isPublic: false
  • containerReference variable values match the target container's name exactly
  • Secrets are typed as secret
  • Health check enabled: is a boolean, not a string