An interrupted first boot silently bricks the instance: starter import leaves site permissions unwritten and every Apps API call 403s forever
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Problem Statement
An interrupted first boot leaves a dotCMS instance permanently unusable, and neither the restart nor the logs tell the user. Every Apps API call returns 403 forever. The only recovery is destroying the volumes and starting over.
This was found while diagnosing #37262 (the @dotcms/create-app CLI failure). It is the backend half of that issue and is filed separately because it is broader than the CLI: any interrupted first boot hits it, whatever started the container.
Steps to Reproduce
Using docker/docker-compose-examples/single-node-demo-site/docker-compose.yml:
docker compose up -dfrom clean volumes.- ~25s in — during the starter import, while
ImportStarterUtilis processingcom.dotmarketing.beans.Tree— kill the dotCMS container:docker kill <dotcms>. - Start it again:
docker start <dotcms>. It boots and reports a clean startup. - Issue an API token as
admin@dotcms.com, resolve the default site, then call the Apps API for that site.
Expected Behavior
Either the instance repairs itself on restart (re-running the incomplete import), or it fails loudly — refusing to serve, logging a clear "incomplete initialization" error, and telling the operator to recreate the instance.
Actual Behavior
Startup looks completely normal:
14:05:24 INFO db.DotCMSInitDb - There are no inodes - initializing db with starter site
14:05:24 INFO db.DotCMSInitDb - STARTER_DATA_LOAD property is set to ...zip, loading starter data
14:05:50 INFO startup.Catalina - Server startup in [37136] milliseconds
But the admin user has no permissions on the site that was supposedly imported:
DotSecurityException: User 'Admin User [ID: dotcms.org.1][email:admin@dotcms.com]'
does not have READ permissions on Site 'demo.dotcms.com'
Every Apps API call 403s, and it never clears:
T+39s /api/v1/appconfiguration -> 200
T+41s POST /api/v1/authentication/api-token -> 200
T+41s GET /api/v1/site/defaultSite -> 200
T+41s GET/POST /api/v1/apps/dotema-config-v2/{siteId} -> 403
… 193 consecutive attempts over ~7 minutes …
T+440s GET/POST /api/v1/apps/dotema-config-v2/{siteId} -> 403
193 attempts, zero successes. Waiting does not help. A clean boot of the same stack returns 200 for all three calls at 46s.
Analysis
The interrupted import left the site's permission rows unwritten. On restart DotCMSInitDb still reported "There are no inodes" and re-ran Task00004LoadStarter, but the permissions never appeared — so the re-run did not restore the state the first run left half-written.
Three things seem wrong, in increasing order of severity:
- The re-run does not repair.
Task00004LoadStarterruns again but the resulting instance is still missing permissions. - The failure is silent. Startup logs report success. Nothing indicates the instance is unusable.
- The symptom is misleading. A missing-permissions data problem surfaces to every client as
403 Forbidden, which reads as an auth or licensing problem. In #37262 this cost significant investigation time — the original hypothesis blameduser.isAdmin()swallowing an exception viaTry.of(…).getOrElse(false), which turned out to be wrong: there is no exception, the data is simply absent.
A partially-imported starter arguably should not be committed at all — if the import is not atomic, an interruption leaves a state the system cannot distinguish from a valid one.
Impact
High for first-run experience. Anyone whose first boot is interrupted — a crash, a laptop sleeping, Ctrl-C, an OOM kill, a container racing its database — gets an instance that looks healthy and is permanently broken, with no diagnostic pointing at the cause. This is the mechanism behind the user-visible failure in #37262.
Environment
dotcms/dotcms:latest · single-node-demo-site compose · starter 20260630 · macOS + OrbStack, dotCMS constrained to 2 CPUs / 4G.
Evidence limits: one host, one starter, one image, kill point fixed at 25s. Which kill-points corrupt and which are survivable is unmapped.
Related
- #37262 —
@dotcms/create-applocal Docker failure; this is its backend half
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with DotCMSInitDb and Task00004LoadStarter, then trace the starter import through ImportStarterUtil. Reproduce the interrupted import using docker/docker-compose-examples/single-node-demo-site/docker-compose.yml and check whether site permission rows survive a restart. Done means an interrupted first boot either recovers correctly or reports a clear incomplete-initialization failure instead of serving persistent 403 responses.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker, docker-compose, java
- Domain
- backend, databases, devops
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100