Troubleshooting
Symptoms first, diagnosis second. Most issues fall into one of these categories — start with the matching section.
Daemon won’t start
Section titled “Daemon won’t start”Symptom: norsk-ctl <anything> errors with a connection refused or “daemon not reachable” message.
Check, in order:
- Is the config present?
~/.norsk-ctl/config.yamlis read at boot. Missing or unparseable config means the daemon exits immediately.If missing, runTerminal window ls -l ~/.norsk-ctl/config.yamlnorsk-ctl config shownorsk-ctl init. - Is the port free? Default is
8333(override viaNORSK_CTL_PORT).Terminal window ss -tlnp | grep 8333 - systemd service running? On
--serverinstalls:Terminal window sudo systemctl status norsk-ctlsudo journalctl -u norsk-ctl -n 200 --no-pager - Docker reachable? The daemon shells out to Docker for every instance op.
docker psshould return cleanly as the same user the daemon runs as. On Linux, the daemon user must be in thedockergroup —norsk-ctl restartrefuses to bounce when the current shell isn’t in the group yet (you’d just re-create the problem).
product add rejects the license
Section titled “product add rejects the license”Symptom: norsk-ctl product add … exits non-zero (or the Add Product form shows a 400) complaining about the license file. Nothing is registered.
- “not a V2 license envelope”? The file is readable but isn’t a signed V2 envelope. Two quite different causes share this message, so check the path before assuming the license is at fault:
- The path points at the wrong thing — an HTML error page from a failed download, a truncated file, the wrong
.json.head -c 200 <file>settles it in one look. - It really is an older V1 license. Those are no longer accepted when registering a product (V2 is required) and must be reissued — contact Norsk support.
- The path points at the wrong thing — an HTML error page from a failed download, a truncated file, the wrong
- “license has no entry for product …”? The file is a valid V2 envelope but doesn’t cover this product — the message lists what it does cover. If it names the product but you still get an error, the entry covers a different image or version than the one you passed to
--image— andnorsk-ctl product add --license-file <file>with no--imageregisters exactly what the license entitles, so dropping--imageis usually the fix. - “license expired at …”? A V2 envelope carries an expiry for the license and one per product entry; either lapsing is rejected with the date. Reissue it.
- Registration succeeded but warned it “was not validated”? The daemon could not read the file (usually permissions — it runs unprivileged, while Docker mounts the license as root). Registration is allowed to proceed, but nothing was checked: if it turns out to be a V1 license, the engine rejects it at launch instead. Make the file readable by the daemon user and re-add to get a real answer.
Launch hangs or instance never reports healthy
Section titled “Launch hangs or instance never reports healthy”Symptom: instance launch-template returns, but instance describe shows status: starting for minutes.
- Image pull in progress? First launch on a fresh box pulls the studio (~1.5 GB) and media (~2 GB) images. Watch with
docker pullrunning separately orjournalctl -u norsk-ctl -f. - License rejected? Studio refuses to start without a valid license. Check the studio container logs (compose names containers
<id>-<service>-1):Terminal window docker logs <id>-studio-1 --tail 100 - Port collision. Ingest ports (SRT/RTMP/etc.) are published directly to the host. Two instances binding the same host port will fail — second one stays stuck.
- Workflow YAML invalid. A malformed workflow drops Studio into an error state. Visit
/instance/<id>/studio/in the browser; the canvas surfaces the parse error.
Launch refused with a HARDWARE_… code
Section titled “Launch refused with a HARDWARE_… code”Symptom: instance launch-template fails immediately (or the launch form blocks) with HARDWARE_NOT_FOUND, HARDWARE_UNAVAILABLE, HARDWARE_PINNED, or HARDWARE_REQUIRED. Nothing was started.
The runner checked the requested accelerator against the host before touching Docker, and the code names why it stopped. Start with norsk-ctl get hardware: accelerators lists what the host actually carries.
HARDWARE_NOT_FOUND—quadrawas requested but no NETINT card was found. The probe looks for an NVMe controller under/sys/class/nvmewith PCI vendor0x1d82; ifcat /sys/class/nvme/*/device/vendorshows nothing of the kind, the card’s driver is not loaded or the card is not seated.HARDWARE_UNAVAILABLE— the product requires an accelerator this host does not have. Launch it elsewhere; if the product only prefers it (adefaultdeclaration), pass--hardware noneto run unaccelerated.HARDWARE_PINNED— you asked for an accelerator the product does not allow. Drop--hardware; the product’s manifest decides.HARDWARE_REQUIRED— the product leaves the choice to you and none was made. Pass--hardware nvidia,--hardware quadra, or--hardware none.
A launch that passes these checks but fails in compose with could not select device driver "nvidia" is on a CDI-only host the runner classified as legacy; set NORSK_CTL_GPU_MODE=cdi in the daemon’s environment and relaunch. Hardware Acceleration has the full picture.
Proxy returns 502
Section titled “Proxy returns 502”Symptom: Public URL serves a 502 / “upstream unavailable” from nginx.
- Instance not running?
norsk-ctl instance list— does the target instance still exist? If you deleted it, the URL is dead. - Stale nginx config?
norsk-ctl proxy reloadregenerates nginx config from the daemon’s current view. Launch/teardown paths trigger it automatically, and the daemon also reloads on Docker start events — so a container restarted behind norsk-ctl’s back (docker restart) self-heals within a second or two. A persistent 502 after that points elsewhere;norsk-ctl proxy statusshows the active upstreams. - Daemon down behind the proxy? Requests to
/api/and/proxy tohost.docker.internal:8333. If the daemon stopped, the proxy survives but every backend request 502s.
Instance shows stopped but containers are still running (or vice versa)
Section titled “Instance shows stopped but containers are still running (or vice versa)”norsk-ctl tracks instance state in ~/.norsk-ctl/norsk-ctl.db. Drift happens if you docker rm containers behind its back, or if the daemon was killed mid-operation.
# What does docker think is running? Each instance is a compose# project named by its instance id.docker compose ls
# What does norsk-ctl think?norsk-ctl instance listIf they diverge: norsk-ctl instance restart <id> reconciles by tearing down and re-launching. norsk-ctl instance delete <id> followed by a fresh launch is the heavy-handed reset.
Plugins aren’t discovered
Section titled “Plugins aren’t discovered”Symptom: the Studio product’s plugin listing (GET /products/norsk-studio/api/plugins?workingDirectory=…) doesn’t show a plugin you’ve dropped under <workingDirectory>/plugins/.
- Missing
package.json? Discovery requires a readablepackage.jsonwith a non-emptynamefield. Directories without one are skipped with a warning. - Wrong working directory. Every plugin endpoint takes an explicit
workingDirectory— there’s no daemon-side default. Check the path you passed matches where the plugin actually lives. - Plugin not in the instance? Instances only load plugins baked into the image (pinned by the product template) or listed in the product template’s
server.library. Dropping files underplugins/alone doesn’t affect a launch. See Manage plugins.
Studio loads a blank canvas
Section titled “Studio loads a blank canvas”- Workflow YAML missing? The workflow save-file ships with the product template. If the product template references a save file that isn’t present in the working directory, Studio silently lands on an empty canvas. Check
instance describeand the product template’s bundled save files. - Library not loaded. Workflows reference nodes from named libraries. If the workflow uses a node from a package the product template’s library list doesn’t include, the canvas loads but the node is broken. See Studio libraries.
TLS browser warning persists after mkcert -install
Section titled “TLS browser warning persists after mkcert -install”macOS browsers cache trust decisions per-session. Fully quit and restart the browser (cmd-Q, not just close window). Firefox uses its own cert store — brew install nss before mkcert -install so Firefox is reached too.
Public IP couldn’t be auto-detected at install
Section titled “Public IP couldn’t be auto-detected at install”Symptom: install.sh --ip auto aborts with couldn't auto-detect a public IP.
--ip auto probes https://api.ipify.org then https://ifconfig.me (each 5-second timeout). If neither responds, pass --ip <host> or --public-host <name> explicitly. On a private network without outbound HTTPS, this is expected.
How to gather diagnostics
Section titled “How to gather diagnostics”When in doubt, capture:
norsk-ctl status(orstatusvia MCP)norsk-ctl config shownorsk-ctl instance listandinstance describe <id>for the affected instancejournalctl -u norsk-ctl -n 500 --no-pagerdocker compose lsanddocker logs <id>-<service>-1for any wedged containers
The web UI’s Logs view surfaces studio + media + proxy logs without the docker CLI.