Skip to content

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.

  1. Open the subscription form.
  2. Click Action → Diagnosis & Fix.
  3. A "started in background" confirmation appears in the chatter immediately — the button does not block.
  4. Wait 10–60 seconds for the full HTML report to appear in the chatter.
  5. If all checks pass, the subscription state changes to Running automatically.
  6. 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.

  1. Click Action → Reset to Draft on the subscription form.
  2. Fix the underlying configuration issue (domain, image, environment, server group).
  3. 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:

  1. Go to the Cloudflare dashboard → My Profile → API Tokens.
  2. Confirm the token is active and has the Zone → DNS → Edit scope for the correct zone.
  3. In Odoo, go to SAAS Management → Infrastructure → Cloudflare Accounts → <account> and confirm the Zone ID matches.

Resolution:

  1. Regenerate or correct the token in the Cloudflare dashboard.
  2. Update the token on the Cloudflare account record in Odoo.
  3. 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:

  1. Go to SAAS Management → Infrastructure → Nginx Servers → <server>.
  2. Click Test Connection — confirm it succeeds.
  3. Open the NPM web UI directly at the configured URL to confirm it is running.

Resolution:

  1. Fix the NPM URL or credentials on the Nginx server record.
  2. Restart NPM if it has crashed.
  3. 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:

  1. Log into the NPM web UI and inspect the proxy host's SSL certificate status.
  2. Check https://crt.sh/?q=yourdomain.com for recent issuance attempts.
  3. Confirm DNS is resolving: dig A yourdomain.com @1.1.1.1

Resolution:

  1. Wait for DNS propagation to complete (confirm with dig above).
  2. Delete the proxy host in the NPM web UI.
  3. Run Diagnosis & Fix — it recreates the host and requests a fresh certificate.
  4. 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:

  1. Go to SAAS Management → Infrastructure → Portainer Servers → <server> → Environments → <environment>.
  2. Click Test Connection.

Resolution:

  1. Restore connectivity to Portainer.
  2. If the environment was recreated, update the environment ID in the Portainer environment record.
  3. 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:

  1. Correct the image name or tag in SAAS Management → Infrastructure → Portainer → Images → <image>.
  2. If the registry requires credentials, configure them in Portainer under Registries.
  3. 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>
Or check Portainer for other stacks using the same 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:

  1. Check the DBFilter server record for the correct URL and master password.
  2. Try creating the database manually via /web/database/manager on the target Odoo server.

Resolution:

  1. Fix the master password or server URL in the DBFilter server record.
  2. If the database name conflicts with an existing one, update the subscription domain to produce a different database name.
  3. 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:

  1. On the subscription form, re-select the DBFilter Server Group field — saving the selection repopulates the port fields from the server group defaults.
  2. Alternatively, click Confirm again — the confirm action triggers automatic port population.
  3. Then click Build.

Aftermath: No Diagnosis & Fix is needed for this case — fix the port configuration, then Confirm → Build.