“My code works every time, always…” is what I wish I could say! Debugging dotCMS is less about panic and more about knowing where to look. When something doesn’t behave the way you expect, it’s usually not broken — it’s just cached, hidden, or quietly trying to tell you what’s wrong.
The good news? dotCMS gives you excellent tools to figure things out quickly once you know how to use them. This guide walks through the most reliable places to check when something feels off, confusing, or just plain stubborn.
Step 1: Flush dotCMS Cache (Fastest First Check)
If something in dotCMS isn’t behaving the way you expect, this should be your first stop. dotCMS is designed for speed, and that means it caches a lot. Most of the time, when something looks broken, it’s actually just the system doing its job a little too well.
When cache is the likely culprit
Content updates don’t appear
Template changes aren’t reflected
APIs return outdated data
Permissions seem inconsistent
Where to clear cache in dotCMS
You can do this from: Maintenance → Cache → Flush, or clear specific caches if you want to be more surgical.
Start here. This is the easiest first step to trying to solve those “Why isn’t this working?” headscratchers.
Step 2: Use Maintenance Logs to Find the Root Cause
The Maintenance → Logs section is your best friend when debugging. It shows you exactly what the system is doing behind the scenes — including things the UI politely ignores.
What you’ll typically find here:
Velocity or template errors
API and permission issues
Content rendering problems
Helpful stack traces that point directly to the cause
Most issues leave breadcrumbs in the logs before you ever notice something’s wrong in the UI. Checking here early can save you a ton of time. When debugging locally, keep the logs open while you work. Watching messages appear in real time makes it much easier to connect cause and effect.
Pulling environments to localhost
You can use the following script to pull your current copy of dotCMS to your local environment. The script is set up to use the most recent copy of dotCMS Evergreen, but there are other versions available for:
dotcms/dotcms-dev:24.12.27_lts_v8
dotcms/dotcms-dev:23.10_lts
dotcms/dotcms-dev:24.04_lts
export TOK={Get your token from the Users -> (Select a user)-> API Access Tokens}
export TOK={Get your token from the Users -> (Select a user)-> API Access Tokens}
export TOK={Get your token from the Users -> (Select a user)-> API Access Tokens}
docker run --rm \
-p 8443:8443 \
-v $PWD/data:/data \
-e CMS_JAVA_OPTS=-XX:UseSVE=0 \
-e DOTCMS_SOURCE_ENVIRONMENT={Replace with dotCMS URL no /} \
-e DOTCMS_API_TOKEN=$TOK \
dotcms/dotcms-dev:nightly <-- Evergreen development version, replace with version above
The above script will pull down a copy of dotCMS to run locally, including all of your current assets. You can then work in this environment worry-free that you will accidentally affect your production environments.
Step 3: Inspect Contentlet JSON and Validate Output via the API Button
Under the ‘History’ tab, every contentlet has a button towards the right hand side of the screen called ‘API’. If you’ve never clicked on this button, I urge you to give it a try!
The API View on a contentlet shows you the raw JSON data exactly as dotCMS sees it. This is a great way to check your contentlet variables and to make sure any data mapping you have is correct.
Use it to:
Verify field values
Confirm relationships
Check language fallbacks
Debug headless/API output
Validate what your frontend should be receiving
This is especially powerful when you’re working with VTL and something isn’t rendering the way you expect. Instead of guessing at variable names or wondering whether a field exists, you can see the exact structure dotCMS is working with.
It’s also incredibly useful when working headless or with AI-assisted development. Feeding the raw contentlet JSON into an AI gives it the full, accurate picture of your schema.
Step 4: Inspect Browser Network Traffic (Endpoint, Params, Payload)
This last tip feels almost more like a hack than anything. Because dotCMS is API driven, most calls to the server are logged in the Network tab. You can open your developer tools/inspector and click over to the network tab.
If there is a specific function you are trying to pinpoint, like adding a contentlet onto a page, or firing a workflow action through code, you can watch the network traffic to see:
Which endpoint is being called
The structure of data being sent to that endpoint
The structure of the data being returned
For example, when I drag a piece of content into a container, the following API endpoint is hit:
/api/v1/page/da1c7e3ef6f49ac1ac563f67cd3ca652/content
Because there is an identifier in the URL, I can tell what page that container exists on.
Clicking over to the ‘Payload’ tab, I can inspect the JSON being sent to the endpoint so I know how to structure my data:
And then I can go to the ‘Response’ tab to inspect the JSON I receive back from that endpoint:
Step 5: Use the dotCMS API Playground (Swagger) to Confirm API Behavior
And speaking of API POST/Responses, have you seen the API playground? You’ll find it under Developer Tools → API Playground, and it’s one of the most useful features in dotCMS. The playground gives you a full Swagger-style interface for every available endpoint, all in one place.
This means you can:
Explore endpoints without guessing URLs
See required parameters and response structures
Test requests instantly, without writing code
Validate permissions and authentication behavior
In the example below, I used the GET /api/v3/contenttype/{typeIdOrVarName}/fields endpoint to list every field in the Blogs Content Type, along with its metadata and configuration.
This is incredibly helpful when:
You’re building or debugging headless integrations
You need to confirm field names or data types
You want to understand how dotCMS exposes content internally
You’re troubleshooting why a field isn’t appearing in an API response
Think of the API Playground as your truth source for anything API-related. If you’re unsure how dotCMS expects a request to look or what it’s going to return, this is the fastest way to find out.
Final Thoughts
Hopefully, these tips give you a solid starting point the next time something in dotCMS does not behave the way you expect. This is not meant to be an exhaustive guide. dotCMS is a large platform with many moving parts, but these techniques cover the most useful first steps when debugging.
Once you get comfortable using these tools, debugging stops feeling like guesswork and starts feeling methodical and even satisfying. And when something does go wrong, you will know exactly where to look first.