Skip to content

Troubleshooting

Sipke Schoorstra edited this page Aug 12, 2026 · 4 revisions

Troubleshooting


Start here

docker logs elsa-pro                              # what actually went wrong
curl -f http://localhost:8080/health              # is it up
docker ps -a                                      # did it exit, and with what code

# what config actually landed
docker inspect elsa-pro --format '{{json .Config.Env}}' | tr ',' '\n' | grep -i cshells

⚠️ You cannot docker exec into these images. They are chiselled: no shell, no printenv, no cat, no curl. docker exec elsa-pro printenv fails with executable file not found in $PATH — that is the image being minimal, not the container being broken. Everything below inspects from the host instead.

Most problems are one of three things: config landing somewhere other than where you think, a URL that resolves in the wrong network context, or a package that never loaded.


Configuration seems to be ignored

Environment variables beat the mounted file. A stray -e from an earlier experiment silently overrides /config/config.json.

docker inspect elsa-pro --format '{{json .Config.Env}}' | tr ',' '\n' | grep -i cshells

Precedence, later wins: appsettings.json → appsettings.{Environment}.json → /config/config.json → environment variables. → Configuration

Also check the file is actually mounted where the app looks. docker cp reads out of the container without needing anything inside it:

docker cp elsa-pro:/config/config.json - | tar -xO

An invalid JSON file may be skipped rather than fatal — so a stray trailing comma looks exactly like "my settings are ignored". Validate it:

python3 -m json.tool config.json > /dev/null && echo "valid"

Note the shipped config.example.json contains // comments as documentation. Strip them before use if your tooling rejects them.


Admin user isn't created / can't sign in

The most common cause: the shell key is wrong.

✅ CShells__Shells__Default__Features__DefaultAdminUser__AdminUsername
❌ CShells__Shells__0__Features__DefaultAdminUser__AdminUsername

Shells is keyed by shell name, not index. Using 0 doesn't error — it defines a different shell called 0, and your admin user is provisioned into a shell you aren't using.

docker inspect elsa-pro --format '{{json .Config.Env}}' | tr ',' '\n' | grep DefaultAdminUser

Other causes:

  • Identity persistence isn't configured, so the user has nowhere to be stored. Both workflow and identity persistence must be set. → Persistence and Databases
  • The user was created in an earlier database that has since been replaced. The admin is provisioned on first start against an empty store; changing the password in config afterwards does not update an existing user.
  • Signing key changed, invalidating existing sessions. Sign in again.

Studio loads but can't reach the API

Nearly always a hosting-model/URL mismatch. → Choosing an Image

WebAssembly (the default): the browser calls the API.

  • Studio__Client__Backend__Url must resolve from the user's machine. http://elsa-server:8080 is a Docker network name and will not resolve in a browser.
  • The server needs a CORS origin matching Studio's origin.

Blazor Server: the container calls the API.

  • Backend__Url (no Client segment) must resolve inside the container — a Docker service name is correct here.
  • No CORS needed.

Diagnose from the browser's network tab: requests to a hostname that doesn't resolve, or CORS errors, tell you immediately which side is misconfigured.

# Reachable from the browser's perspective?
curl -f http://localhost:8080/elsa/api

# Reachable from inside the Studio container? There is no curl in the image, so borrow
# the Studio container's own network namespace with a throwaway one that has curl —
# same DNS, same network, so it answers the question the container would.
docker run --rm --network container:elsa-studio curlimages/curl:latest \
  -f http://elsa-server:8080/elsa/api

CORS errors

Access to fetch at 'http://localhost:8080/elsa/api' from origin
'http://localhost:8081' has been blocked by CORS policy

Add Studio's origin to the server:

-e Elsa__Cors__AllowedOrigins__0=http://localhost:8081

The origin must match exactly — scheme, host and port. http://localhost:8081 and http://127.0.0.1:8081 are different origins.

Not needed at all with Blazor Server or the combined image. If you're fighting CORS, consider whether you want one of those instead.


Container won't start

docker logs elsa-pro
docker ps -a          # exit code
Symptom Likely cause
Database connection errors DB not ready or unreachable. Use depends_on: condition: service_healthy
Migration failures DB user lacks DDL permission, or a partially-migrated schema from a failed upgrade
Nuplane resolution errors Feed unreachable, or a version range matching nothing → Extending with Nuplane
Port already allocated Something else on 8080 — remap the host side
Exit 137 OOM-killed. Raise the memory limit

A feature won't activate

A package can load while its feature stays off. Work through, in order:

  1. Is the package in an IncludePatterns on a reachable feed?
  2. Can the container reach the feed? Egress-filtered networks fail silently here.
  3. Does the version range match a package that exists?
  4. Is the feature name spelled exactly right?
  5. Is it under the shell you're running — Default?
docker logs elsa-pro 2>&1 | grep -i nuplane

Data disappeared after a restart

You're on the default SQLite store, inside the container's writable layer. docker rm destroys it.

Move it to a volume, or better, use a real database. → Persistence and Databases


Workflows execute twice

Multiple replicas without distributed coordination. Each instance independently fires schedules and processes triggers.

You need a shared database, a message bus, and distributed runtime features enabled — or scale back to one replica. → Extending with Nuplane · Production Checklist


Scheduled workflows don't fire after a restart

In-memory scheduling doesn't survive restarts. Use durable Quartz scheduling backed by your database. → Extending with Nuplane


Callback URLs point at localhost

Set the externally reachable base URL:

CShells:Shells:Default:Features:Http:HttpActivityOptions:BaseUrl = https://elsa.example.com

This is what Elsa uses to build callback URLs handed to external systems, so it must be what a caller outside your network would use.


Can't pull a paid image

Error response from daemon: denied
  • Logged in with your subscription token? echo "$VALENCE_REGISTRY_PASSWORD" | docker login valenceruntimeimages.azurecr.io -u YOUR_TOKEN_NAME --password-stdin
  • Correct path? valenceruntimeimages.azurecr.io/runtime-combined, not the Docker Hub name and not a ghcr.io name — those are the free Community images.
  • Correct tag? runtime-studio is versioned on Elsa Studio, so its tag differs from the other two.
  • Subscription current? The token password carries an expiry aligned to your subscription period, so an expired subscription looks exactly like a wrong password.

⚠️ docker login succeeding does not mean you have access. The registry hands a token to any well-formed credential and only checks permissions when you pull. If you are diagnosing this, test a docker pull — a successful login proves nothing.

See Pulling Images for the full access model.


Still stuck

Include, or it'll be the first thing you're asked for:

  • Image name and exact tag
  • docker logs output around the failure
  • Your config.json with secrets redacted
  • What you expected versus what happened
  • Whether it reproduces without custom Nuplane packages
Where For
Issues Image, packaging, deployment
Discussions Questions
elsa-core issues Engine bugs
Your private channel Paid tiers — anything, with a response commitment

→ Editions and Support

Clone this wiki locally