Build Failed
A subscription enters Build Failed state when one of the three provisioning steps — DNS, Nginx, or Instance — throws an error. The error text is stored in the Build Fail Message field. It appears as a red banner near the top of the subscription form (visible in any state) and can also be found by scrolling to the Build Steps section.
Build Sequence
Step 1: DNS → Create Cloudflare A record (skipped if Auto create DNS = false)
Step 2: Nginx → Create proxy host in Nginx Proxy Manager with SSL
Step 3: Instance → Deploy Docker stack on Portainer / create DBFilter database
Each step sets a boolean flag (build_step_dns, build_step_nginx, build_step_instance). When a step fails, the subscription moves to Build Failed and records the error. On retry, only the failed step and any subsequent steps are re-run — already-completed steps are left untouched.
Diagnosis & Fix
This is the fastest path to resolving a Build Failed state. Try it before making any manual changes.
- Open the subscription form.
- Click Action → Diagnosis & Fix.
- A "started in background" confirmation appears in the chatter immediately — the button does not block.
- Wait 10–60 seconds for the full HTML report to appear in the chatter.
- If all checks pass, the subscription state changes to Running automatically.
- If any component is still marked ❌, address it manually using the relevant section below, then re-run Diagnosis & Fix.
Tip
Diagnosis & Fix can also be run on individual stages from the stage list — look for the Diagnosis button next to each stage row.
Reset to Draft
Use Reset to Draft when the subscription configuration itself is wrong — wrong domain, wrong environment, wrong image — and you need to start the build from scratch.
When to use it: the wrong Docker image was selected, the domain needs to change, or the Portainer environment was misconfigured before the first build.
- Click Action → Reset to Draft on the subscription form.
- Fix the underlying configuration issue (domain, image, environment, server group).
- Click Confirm, then Build.
What is preserved: customer, package, Docker image selection, domain configuration, all Many2one links (Nginx server, Cloudflare account, Portainer environment, backup server).
What is cleared: http_port, websocket_port, build_step_* flags, build_fail_message, stack_id.
Warning
Do not Reset to Draft simply to retry a transient failure (network timeout, temporary API error). Use Diagnosis & Fix for those cases — it retries without losing port assignments or stack references.
DNS Failures
Cloudflare API auth failure
Symptom: build_fail_message contains DNS creation failed: Could not create cloudflare DNS record, status code: 401 or 403.
Likely cause: API token expired, token missing the required scope, or the Zone ID on the Cloudflare account record doesn't match the domain's zone.
How to verify:
- Go to the Cloudflare dashboard → My Profile → API Tokens.
- Confirm the token is active and has the Zone → DNS → Edit scope for the correct zone.
- In Odoo, go to SAAS Management → Infrastructure → Cloudflare Accounts →
<account>and confirm the Zone ID matches.
Resolution:
- Regenerate or correct the token in the Cloudflare dashboard.
- Update the token on the Cloudflare account record in Odoo.
- Run Diagnosis & Fix — it retries the DNS step automatically.
Domain already exists in Cloudflare (error 81058)
Symptom: build_fail_message contains DNS creation failed: Record already exists on Cloudflare but could not be found.
Likely cause: A DNS record for this domain was created manually or left over from a previous failed attempt.
How to verify: Log into the Cloudflare dashboard → DNS tab for the zone → search for the domain name.
Resolution: Run Diagnosis & Fix — it detects error 81058, searches for the existing A record, and links it to the subscription automatically. No manual deletion is needed.
Aftermath: DNS step is marked complete and Diagnosis & Fix continues with the Nginx step.
Auto-create disabled but no wildcard exists
Symptom: The build completes without error (DNS step was skipped) but the domain does not resolve in a browser.
Likely cause: Auto create DNS record is set to false on the subscription, but no wildcard A record covers the subdomain in Cloudflare.
How to verify:
dig A subscription.yourdomain.com @1.1.1.1
# Returns NXDOMAIN if no wildcard or explicit record exists
Resolution: Choose one of:
- Add a wildcard record
*.yourdomain.com → <server_ip>in Cloudflare, or - Enable Auto create DNS record on the subscription and re-run Diagnosis & Fix to create the explicit record.
Aftermath: No build retry is needed — the DNS issue is external to the build sequence.
Nginx Failures
NPM API unreachable
Symptom: build_fail_message contains Nginx creation failed: followed by a connection error or timeout.
Likely cause: Nginx Proxy Manager is down, the URL configured in Odoo is wrong, or a firewall rule blocks the connection from the Odoo server.
How to verify:
- Go to SAAS Management → Infrastructure → Nginx Servers →
<server>. - Click Test Connection — confirm it succeeds.
- Open the NPM web UI directly at the configured URL to confirm it is running.
Resolution:
- Fix the NPM URL or credentials on the Nginx server record.
- Restart NPM if it has crashed.
- Run Diagnosis & Fix to retry the Nginx step.
SSL certificate generation failure
Symptom: The Nginx host was created but SSL shows an error, or build_fail_message contains certificate.
Likely cause: Let's Encrypt rate limit was hit, DNS had not propagated when NPM requested the certificate, or NPM cannot reach Let's Encrypt from the server.
How to verify:
- Log into the NPM web UI and inspect the proxy host's SSL certificate status.
- Check
https://crt.sh/?q=yourdomain.comfor recent issuance attempts. - Confirm DNS is resolving:
dig A yourdomain.com @1.1.1.1
Resolution:
- Wait for DNS propagation to complete (confirm with
digabove). - Delete the proxy host in the NPM web UI.
- Run Diagnosis & Fix — it recreates the host and requests a fresh certificate.
- If a Let's Encrypt rate limit was hit, wait 1 hour before retrying.
Aftermath: After DNS propagates, Diagnosis & Fix can recreate the Nginx host and SSL certificate cleanly.
Domain already proxied in NPM
Symptom: The Nginx step fails with a duplicate host error from NPM.
Likely cause: Another NPM proxy host already uses this domain — either from a previous failed build or a manually created entry.
How to verify: Log into the NPM web UI and search for the domain name among proxy hosts.
Resolution: Run Diagnosis & Fix — it finds the existing host and links it to the subscription. If the existing host belongs to a different subscription or was created manually, delete it in NPM first, then re-run Diagnosis & Fix.
Instance Failures — Docker
Portainer environment offline
Symptom: build_fail_message contains Instance creation failed: with a connection or timeout error.
Likely cause: Portainer is unreachable, or the environment ID stored in Odoo no longer matches the environment in Portainer (e.g., after a Portainer reinstall).
How to verify:
- Go to SAAS Management → Infrastructure → Portainer Servers →
<server>→ Environments →<environment>. - Click Test Connection.
Resolution:
- Restore connectivity to Portainer.
- If the environment was recreated, update the environment ID in the Portainer environment record.
- Run Diagnosis & Fix to retry the instance step.
Docker image not found
Symptom: build_fail_message contains Instance creation failed: with image not found or the Portainer stack fails to pull.
Likely cause: The image name or tag is wrong, or the registry requires authentication not configured in Portainer.
How to verify: From the Docker host, try pulling the image manually:
docker pull <image>:<tag>
Resolution:
- Correct the image name or tag in SAAS Management → Infrastructure → Portainer → Images →
<image>. - If the registry requires credentials, configure them in Portainer under Registries.
- Use Reset to Draft on the subscription, re-select the corrected image, then Confirm → Build.
Aftermath: Reset to Draft is required because the image reference is locked in once a build attempt starts.
Port allocation conflict
Symptom: build_fail_message contains Instance creation failed: with port is already allocated or bind for 0.0.0.0:PORT failed.
Likely cause: Another service or Docker container on the host is already using the port Sadeem assigned to this subscription.
How to verify: On the Docker host:
ss -tlnp | grep <port>
Resolution: Diagnosis & Fix detects port conflicts automatically and assigns a new port (next_port + 3). Run Diagnosis & Fix and it handles the reassignment. If the automatic fix fails, manually update the HTTP Port field on the subscription and re-run.
Aftermath: The Nginx proxy configuration is updated automatically when the port changes.
Instance Failures — DBFilter
Database creation failed
Symptom: build_fail_message contains Instance creation failed: Database creation failed: or Could not create Database.
Likely cause: Wrong master password configured on the DBFilter server record, the DBFilter server is unreachable, or a database with the same name already exists on the target server.
How to verify:
- Check the DBFilter server record for the correct URL and master password.
- Try creating the database manually via
/web/database/manageron the target Odoo server.
Resolution:
- Fix the master password or server URL in the DBFilter server record.
- If the database name conflicts with an existing one, update the subscription domain to produce a different database name.
- Run Diagnosis & Fix to retry the instance step.
DBFilter server group not reachable / ports are zero
Symptom: The build fails immediately after Confirm with no build steps recorded, or the HTTP Port and WebSocket Port fields on the subscription show 0.
Likely cause: The DBFilter server in the server group is unreachable, or ports were cleared by a previous Reset to Draft and were not repopulated.
How to verify: Open the subscription form and check the HTTP Port and WebSocket Port fields. If either is 0, the server group defaults were not applied.
Resolution:
- On the subscription form, re-select the DBFilter Server Group field — saving the selection repopulates the port fields from the server group defaults.
- Alternatively, click Confirm again — the confirm action triggers automatic port population.
- Then click Build.
Aftermath: No Diagnosis & Fix is needed for this case — fix the port configuration, then Confirm → Build.