Troubleshooting
the usual problems and their fixes.
Start with two places: the server log (journalctl -u vodmill -n 100 or docker logs vodmill) and the console's System health and Status pages. Most problems are named there.
01The server does not start
| What you see | Cause and fix |
|---|---|
Cannot find module …/dist/src/server/index.js | The build was not run. npm run build in the product folder. |
An error about better-sqlite3 or a missing binding | No prebuilt database driver for your system. Install python3 make g++, then npm ci again. |
A syntax error, or process.loadEnvFile is not a function | Node.js is too old. node --version must be 22.12 or newer. |
EADDRINUSE | Something else uses the port. Change PORT in .env (and in the proxy), or stop the other program. |
| "This database was last used by Vodmill X, but this code is Y." | You installed an older version over newer data. Install X or newer (Updating). |
EACCES on the data folder | The service user does not own the folder: sudo chown -R vodmill:vodmill /opt/vodmill. |
02I cannot find the setup code, or it is refused
The code is printed in the server log on every start until the owner exists: journalctl -u vodmill | grep -A 3 "setup code". Any printed code works until the owner is created. If the owner already exists and you lost the password, use recover-owner.js (First steps).
03"Public URL is https" stays red, or sign-in does not stick
- Set
PUBLIC_URL=https://your-domainin.envand restart, or fill the Server section in the console. - Open the app through the https address, not through
http://server-ip:8787: with an https public URL the cookies are marked Secure and a plain http page cannot keep the session. - Behind nginx, pass
HostandX-Forwarded-Protoas in Installation.
04ffmpeg or ffprobe is "not found"
sudo apt install -y ffmpeg installs both. If they are installed but not on the service's PATH, set full paths in .env and restart:
which ffmpeg ffprobe
# then in .env
FFMPEG_PATH=/usr/bin/ffmpeg
FFPROBE_PATH=/usr/bin/ffprobe
05Uploads fail or stop
| What you see | Cause and fix |
|---|---|
Every piece fails with 413 behind nginx | client_max_body_size is too small. Set 64m (Installation). |
| "This file is larger than N GB, the limit on this server." | Raise "Largest upload (GB)" under System, Rendering. |
| "Upload a video file: MP4, MOV, MKV or WebM." | Other containers are not accepted. Export the video again as MP4. |
| "This video has no sound." | Clips are found through speech; a source needs an audio track. |
| "Ten uploads of this workspace are unfinished." | Finish or delete one in the library. Uploads nobody finishes are removed after two days. |
| An upload stopped half-way | Open the library and choose "Continue the upload" with the same file. |
06A source cannot be analysed, or the analysis fails
| What you see | Cause and fix |
|---|---|
| Status check "Transcription is set up" is red | The chosen provider has no key, or the whisper.cpp paths are wrong (Transcription). |
| "… is rate-limiting this key or its quota is used up" | Your transcription provider's limit. Check its dashboard, or switch provider. |
| "whisper.cpp did not write its result. Is the model file a ggml model?" | The model path points at the wrong file. It must be a ggml-*.bin model. |
| "This video runs N minutes; the … plan allows M." | The plan's "Longest source video". Change the plan or the workspace's plan. |
| "The … plan analyses N minutes a month and M are used." | The plan's monthly minutes. |
| "No clips found" | Nothing passed the bar. Try other lengths or add notes, then analyse again. |
| Clips are picked but without AI titles | No Anthropic key: the built-in picker was used. See the console's AI usage page for failed calls when a key is set. |
When a step fails, the credits charged for it are returned and the source shows the error. "Analyse again" starts over; a finished transcript is reused.
07Renders fail, wait or look wrong
| What you see | Cause and fix |
|---|---|
| Renders wait for a long time | One render runs at a time by default, and one per workspace. Check the console's Render queue. More cores first, then "Renders at the same time". |
| The server becomes slow or the process is killed during renders | Too much parallel work for the machine's memory. Set "Renders at the same time" and "Sources analysed at the same time" back to 1. |
| "Face model not found: put face_detection_yunet_2026may.onnx in the models folder or set VODMILL_YUNET_MODEL" | The models folder is missing next to the app (the Docker image contains it). Put the folder from the package back, or set VODMILL_YUNET_MODEL in .env to the file's full path. |
| "The source file of this clip is gone, so it cannot be rendered." | The source's files were deleted or not restored (Backups). |
| "60 fps renders are not part of the … plan." | 60 fps needs "Allow 60 fps renders" and the plan's limit. |
| The crop follows the wrong person | Set the layout by hand (Layouts). |
| Captions show boxes for some letters | The bundled fonts cover Latin scripts. Other scripts need a system font on the server. |
| Free disk is "low" or "critical" on System health | Delete old sources, set "Delete render files after (days)", or add disk. |
08Other answers you may see
| What you see | Cause and fix |
|---|---|
"The server is working out the framing of other clips. Try again in a few seconds." (429 with retry-after: 5) | Face tracking for the editor's preview is limited to a few clips at once for the whole server. Meanwhile the editor's preview keeps its approximate framing and asks again after the next change to the clip; nothing is lost. |
"Too many links that do not exist were opened from this address. Wait a few minutes." (429) | The guard against guessing share links (Security). Real links are not counted. |
"This service is not available in your country." (451) | The visitor's country is on your blocked list (Security). |
"The canceled analysis is still stopping. Try again in a moment." (409) | A canceled analysis is still letting go of its step. Start the new analysis a few seconds later. |
09Import from a link does not work
| What you see | Cause and fix |
|---|---|
| "Importing from a link is switched off on this server." | The switch is off, or no allowed kind of link is usable: YouTube, Twitch and Kick need the yt-dlp path, direct links must be ticked under "Allowed sites" (Imports). |
| "This link cannot be imported here. Allowed: …" | The link's site is not among the allowed ones on this server. The sentence lists what is allowed. |
| "Importing from a link is not part of the … plan." | Switch on the plan's "Import from a link". |
| "yt-dlp could not be started at …" | Wrong path, or the service user may not run it. With Docker the path must exist inside the container. |
| "Instagram and TikTok links cannot be imported." | By design. Upload the original file. |
| "This video is private or needs a sign-in" / "not available any more" | The video cannot be reached publicly. |
| Imports that worked now fail for one site | The site changed. Updating the program is the operator's task. |
10A customer paid but has no plan or credits
- Stripe dashboard, Developers, Webhooks: open the endpoint and look at the delivery of that payment.
503 Webhook secret not set: paste the signing secret under System, Integrations.400with a signature message: the signing secret does not belong to this endpoint (test and live mode have different ones).- No delivery at all: the endpoint address is wrong, or the five events are not selected (Stripe webhook).
- After fixing it, use "Resend" on the event in Stripe. Each event is applied once. You can also add the credits by hand on the console's Workspaces page.
11E-mails do not arrive
- The Resend key and the Sender must both be set, and the sender's domain verified in Resend.
- The public URL must be set, or reset e-mails are not sent at all.
- Meanwhile: invite links are shown on the page, and the console's Users page makes a password reset link you can send yourself.
12Campaign views are not updating
- Status checks "Campaign views can be counted automatically" and "Campaign view tracking is running" say which key is missing or when the last check ran.
- Only YouTube and Twitch are automatic. For other platforms the clipper uploads a screenshot and a reviewer confirms it.
- Views are read hourly for 48 hours, then daily. "Read views now" on the console's Campaigns page checks at once.
- "Counted views can be lower than the platform shows": open the submission for the reasons (the tracking window, the baseline when views count from submission).
- A clip cannot be approved when the budget is fully reserved: the brand raises the budget.
13Publishing problems
| What you see | Cause and fix |
|---|---|
Google shows redirect_uri_mismatch | The redirect URI in your OAuth client must be exactly <public URL>/api/publish/youtube/callback. |
| Only some people can connect; connections end after a week | Your Google consent screen is in Testing (Publishing). |
| A channel shows "reconnect" | Access was withdrawn or expired. Connect the channel again. |
| Posts fail with a quota message | Your Google project's daily upload quota, shared by all customers, or the channel's own daily limit. |
| A Postiz address is refused | It must be https on port 443 and reachable from the internet. |
| Scheduled posts do not go out | Status check "Scheduled posts are going out"; publishing or that channel kind may be switched off. |
14API and webhooks
403 The API is turned off on this server.: System, Public API.402 The workspace's plan does not include the API.: the plan's "REST API and webhooks".401: the header must beAuthorization: Bearer vdm_….- A webhook that never arrives: Developers, "Deliveries" shows the result of each try. The address must be https and public.
- The same event arrives more than once: a failed delivery is tried up to 3 times with the same event
id. Answer2xxwithin 10 seconds and ignore ids you already handled (Webhooks). - Signature checks fail: verify the raw body, and check the server clocks (a difference over five minutes is refused).
413 Request too large: a JSON body over the limit (Security).422with a sentence: invalid input, in the API and in the app alike (publishing forms included). The sentence says what to correct.
15Still stuck
See Support for what to include in a request. Never send API keys, .env, ADMIN_SECRET_KEY, passwords or backups.