Nodaro Docs
DocumentationNode ReferenceModelsAI Agents (MCP)DevelopersSelf-hostingResearch

Troubleshooting

Fix common problems of a self-hosted Nodaro, starting at /setup. Symptoms and fixes for startup errors, ports, CORS, migrations, storage, queues and keys.

This page lists the most common problems of a self-hosted Nodaro, each with its symptom and its fix. Start with the /setup page, which shows most of them at a glance.

Start at /setup

Self-hosted installs serve a live health screen at http://<your-host>/setup. It needs no sign-in and shows only whether each part is present and working, never a secret.

  • Cards for the database, Redis, storage, the encryption key and the provider keys, green or red. The database card has its own migrations missing state.
  • A hint on every failing card, naming the variables to check.
  • Live updates: the page checks again every 5 seconds.

When the page says API unreachable, the web server is up but the API is not answering. Read the container logs with docker compose -f docker-compose.community.yml logs -f, and check that nothing blocks port 3000.

The install does not start

Missing or invalid env vars on startup. The message lists the variables that failed validation. The usual causes are an empty SUPABASE_SERVICE_ROLE_KEY and an INTERNAL_ORCHESTRATOR_SECRET shorter than 32 characters.

port is already allocated on docker compose up. The stack publishes only two host ports: 3000 for the app and 9001 for the MinIO console, on loopback. Redis and the database never use a host port. Change the host side of the conflicting mapping in docker-compose.community.yml, for example "3001:3000". For the app port, also set PUBLIC_URL to match.

The migrations failed on boot. The app's log names the exact file. The API refuses to start against a half-migrated database. Fix the cause and run docker compose -f docker-compose.community.yml up again: files already applied are skipped.

password authentication failed for user "supabase_auth_admin" in the sign-in logs. The db-data volume is older than the database's role setup, or you changed POSTGRES_PASSWORD after the first start. The role passwords follow POSTGRES_PASSWORD only on the first start. Either delete the volume with docker compose -f docker-compose.community.yml down -v, which deletes your data, or change the role passwords by hand as supabase_admin.

The Docker build fails to download or verify the ffmpeg archive. This only affects you when you build the image yourself. The Dockerfile pins an exact static ffmpeg build per architecture, with ARG FFMPEG_TARBALL_URL_* and ARG FFMPEG_TARBALL_SHA256_*, because rendered audio and video change between ffmpeg versions. A failed download or a checksum mismatch stops the build instead of silently changing your output. Choose a newer dated release of the same builds (BtbN/FFmpeg-Builds on GitHub), and update both the URL and the SHA-256 for both architectures. Treat it as a real ffmpeg upgrade and check your rendered output afterwards.

The browser shows errors

The editor renders, but stays blank or shows "Loading…" forever. Open the browser console.

  • CORS errors: see the next item.
  • Sign-in errors: open /config.js on your install. It must name a Supabase URL that your browser can reach, PUBLIC_URL/supabase on the bundled stack, and the anon key. The container writes it at boot from PUBLIC_URL, FRONTEND_SUPABASE_URL and SUPABASE_ANON_KEY: fix those and restart.

CORS errors in the browser. http://localhost:3000 and PUBLIC_URL are always allowed, so you opened the app on another origin, such as a LAN address or another port. Set PUBLIC_URL to that origin, or list extra origins, comma-separated, in CORS_ORIGIN, for example CORS_ORIGIN=http://192.168.1.20:3000. Then run docker compose -f docker-compose.community.yml up -d.

Edit video shows a panel instead of the editor. The hosted video editor accepts embedding only from http://localhost:3000. On another origin, run your own editor and set FREECUT_URL. See Video and audio editors.

Edit audio shows a panel instead of the editor. There is no hosted audio editor. Run your own AudioMass and set AUDIOMASS_URL.

Database

A migration fails with "relation … does not exist". A migration ran out of order. Apply the files of supabase/migrations/ in filename order, for example in the Supabase SQL editor. Each one can run again on a database where it is already applied.

An OAuth callback returns 500. The tables for OAuth apps are missing because a migration was not applied. Apply every migration in filename order. See Database.

The API restarts in a loop. It cannot reach Postgres. That is expected while the database is down. Once Postgres is back, run docker compose -f docker-compose.community.yml restart nodaro.

Storage

Uploads fail on the bundled stack. Open the MinIO console at http://localhost:9001. The default credentials are in the compose file.

Uploads to Cloudflare R2 answer 401 or 403. Check that the API token has Object Read & Write on the bucket. With a custom domain in front of R2, also check the bucket's public access setting: Nodaro gives the browser public media URLs, so reads must work without authentication.

Every storage request fails with an authorization or endpoint error. Set R2_REGION to the store's region. AWS, DigitalOcean Spaces and a local Supabase reject the default auto, and their error does not mention the region.

Every upload fails after you set STORAGE_OBJECT_ACL. The storage keys lack the right to set object ACLs. Leave the variable empty unless your store refuses a bucket policy.

[storage] failed to create bucket in the boot log with R2. Harmless. R2 tokens cannot create buckets, and yours already exists.

Runs and nodes

Workflows are queued but never start. Read the logs with docker compose -f docker-compose.community.yml logs nodaro. The orchestrator takes its work from Redis, so nothing runs when Redis cannot be reached. Check REDIS_URL and run docker compose -f docker-compose.community.yml exec redis redis-cli ping, which should answer PONG.

A node fails with Missing API key. The node calls a provider that has no key. Add the key on /setup or in .env. See Provider keys.

Images and video work, but every text feature fails. KIE_API_BASE_URL names a proxy that forwards only the media paths. See Send provider traffic through your own proxy.

Pasting a key or connecting to Nodaro Cloud fails with EncryptionKeyMissingError. The install has no encryption key. With a managed Supabase project, set NODARO_ENCRYPTION_KEY, 64 hex characters from openssl rand -hex 32.

Provider keys show missing after a restore. The database was restored without its matching encryption key. See Backups and restore.

A node fails with 503 nodaro_connection_required. It is a Nodaro-exclusive node, which needs a Nodaro Cloud connection. See Connect to Nodaro Cloud.

Cloud runs fail with Token expired. The connection's 90-day token ran out. Click Disconnect, then Connect.

Cloud runs fail with 402 instance_cap_reached. The install reached its monthly spend cap. Raise the cap on app.nodaro.ai, under Billing › Connected Instances.

Healthy runs are marked Execution orphaned. Two installs share one database with separate Redis instances. Give each install its own RUNTIME_ENV. See Scaling.

3D Render Pro answers 503 SCENE_CAPABILITY_UNAVAILABLE. 3D Render Pro runs on a hosted build service and is not part of the self-hosted editions. It never falls back silently to another renderer. Use Generate 3D Scene and Render Video, which run on your server.

Sign-in and MCP

The SSO routes answer 404 unknown_provider. No provider is configured. Check EXTERNAL_SSO_PROVIDERS, and on the compose stack, add it under environment: of the nodaro service. See Single sign-on.

Every API call answers 403 sso_required. The surface profile allows SSO only, and the account was not created or linked through SSO. See Sign-in methods.

An MCP client gets 405 wrong_mcp_host. The client uses the app's main address. Give it the address of your MCP host instead. See MCP.

Updates

The version label shows only the built-in version, and the release notes are empty. The update check cannot read GitHub. The log line [update-check] … read failed: HTTP 403 (rate limit: 0 of 60 left…) means your outbound address has spent GitHub's anonymous quota. Set NODARO_UPDATE_CHECK_TOKEN. See Updating.

Get help

If you are still stuck, open an issue on GitHub with the Docker logs of the app container.

Frequently asked questions

Last updated on

On this page