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:
| Cause | Signs | Fix |
|---|---|---|
| Missing required env var | "Required environment variable X not set" in logs | Ensure 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 start | Increase initialDelay, add retry logic in app |
| Wrong image | "manifest unknown" | Verify image name and tag are correct and accessible |
| Insufficient memory | OOMKilled in status | Increase 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:
| Cause | Fix |
|---|---|
| Health endpoint doesn't exist | Create a /health endpoint that returns 200 OK |
| Wrong path | Update path in x-clouve-healthcheck to match actual endpoint |
| Wrong port | Update port to match your container's listening port |
| App not ready in time | Increase initialDelay |
| Health endpoint requires auth | Remove auth requirement from health endpoint |
| HTTP check on a TCP-only service | Change 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 namedpostgres-db - The value has the wrong capitalization (
Postgres-DBinstead ofpostgres-db) - The
type: containerReferencedeclaration 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:
- Verify the file is valid Docker Compose YAML
- Check that
services:is at the root level (no indentation) - 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:
- Check the application logs. The most specific information is always in the container logs.
- Validate your YAML with
yamllint clv-docker-compose.ymlanddocker-compose config. - Test locally with
docker-compose upto verify the app works outside the platform. - Simplify: start with a single container, get it working, then add complexity.
- 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 (
yamllintpasses) - All container names use lowercase + hyphens only
- All images use specific version tags
- Every container has all four
x-clouve-*blocks -
containerNameinx-clouve-metadatamatches the service key -
memoryBaseis in GB (gibibytes), minimum1:1= 1 GB,2= 2 GB -
cpuBaseis in decimal cores, minimum0.5 - Volume names match between
volumes:,x-clouve-volumes, and top-levelvolumes: - Volume sizes include units and are at least
8Gi - Database containers are
isPublic: false -
containerReferencevariable values match the target container's name exactly - Secrets are typed as
secret - Health check
enabled:is a boolean, not a string