Formatting Migration
How your saved number formats, date formats, and highlight rules move to their new layout when you upgrade, and how to preview, check, and roll back the move
Semaphor stores each column's number and date format, and each highlight rule, with the column it applies to. When you upgrade to a version that includes this change (noted in the Release Notes), Semaphor moves the formats and rules on your existing dashboards, library visuals, and semantic models for you, the first time the new version starts. You don't run a script, and your dashboards look the same afterwards.
What happens during the upgrade
- The migration runs once, when the new version of the API service first starts: after the database schema changes, and before Semaphor starts serving requests.
- Before it changes anything, Semaphor saves a copy of every dashboard, library visual, and semantic model it reads to your data volume, under
/data/backups/card-presentation/. - It's all or nothing: either every dashboard moves, or nothing in your database changes.
- It usually takes a few seconds. A deployment with thousands of dashboards can take a few minutes.
In the API service's startup log you'll see:
Moving saved formats and rules to their new stores (once)...
Card presentation upgrade (apply): {"mode":"apply",...,"written":42,"snapshot":"/data/backups/card-presentation/2026-11-03T15-04-05-123Z",...}written is the number of dashboards, library visuals, and semantic models the migration updated, and snapshot is the folder that holds the copy it took.
The copy stays on your data volume. Keep it until you've confirmed your dashboards look right; after that you can delete the folder.
Before you upgrade
Back up your database
Take a full backup as described in the Upgrade Guide, for the embedded database or your external one.
Preview the migration (optional)
Pin the new version in docker-compose.yml and pull the images. Then run the preview with the new version:
docker-compose pull
docker-compose stop api-service # embedded database only
docker-compose run --rm api-service card-presentation-upgrade --dry-runIf you use the embedded database, stop the API service first: two copies of it can't share the database files. With an external database, you can run the preview while Semaphor keeps running.
The preview changes nothing. It prints how many dashboards, library visuals, and semantic models the migration will update, and counts any saved formatting that has no equivalent in the new layout, usually settings that no longer apply to any column. The same summary is saved under /data/backups/card-presentation/<time>-dry-run/. If you'd like us to review it before you upgrade, send the printed summary to your Semaphor contact.
Check the migration
docker-compose logs api-service | grep -i "card presentation upgrade"A line that starts with Card presentation upgrade (apply) means the migration completed. Then open a few dashboards whose tables or charts use custom number or date formats or highlight rules.
Later restarts don't run the migration again.
If the migration doesn't complete
Semaphor still starts. The startup log says why, then shows:
WARNING: The card presentation upgrade did not finish; the lines above say whether anything changed.
The server starts anyway; the next start tries again.The line above the warning tells you what happened to your data:
- If it ends with
Nothing was written., your database is as it was. Until the migration completes, columns whose formats haven't moved show default formatting. - If it says
The formats and rules were moved, the migration moved everything but couldn't confirm it. The next start confirms it; nothing else is needed.
To try again, restart the API service:
docker-compose restart api-serviceIf it doesn't finish on the next start, contact Semaphor support with the log lines from the startup, including the Snapshot: line if one is shown.
Start without the migration
If you need Semaphor running while you look into a migration that didn't complete, you can turn the migration off. Add this to semaphor.env and restart the API service:
SEMAPHOR_SKIP_CARD_PRESENTATION_UPGRADE=trueColumns whose formats haven't moved show default formatting until you remove the setting and restart.
Roll back to your previous version
To go back to the version you upgraded from, put your dashboards back first, while the new version is still installed:
Stop the API service
docker-compose stop api-serviceFind the copy the migration took
It's the snapshot folder in the startup log line. You can also list the copies on your data volume:
docker-compose run --rm --entrypoint ls api-service /data/backups/card-presentationRestore the copy
docker-compose run --rm api-service card-presentation-upgrade --restore /data/backups/card-presentation/<folder>The restore puts back every dashboard, library visual, and semantic model the migration updated, as long as none has changed since. If one has, it puts back nothing and names it; in that case, restore the full backup you took before upgrading, as described in the Upgrade Guide.
Start your previous version
Set the previous version in docker-compose.yml, then:
docker-compose pull
docker-compose up -dAfter a restore, the migration runs again the next time you start a version that includes it.
If you create dashboards through the API
After you upgrade, dashboard templates you save through the API must use the current format settings. A save that still uses an older setting is refused, with an error that names the setting and the one that replaces it.