gio doctor
Check the environment and the project for what most often breaks a GioJS app, with a fix for every problem. Exits 1 when a check fails.
npx gio doctorpnpm exec gio doctoryarn gio doctorbunx gio doctorgio doctor [--dev | --prod] [--json]Reference
| Option | Type | Default | Description |
|---|---|---|---|
--dev | boolean | - | Check the development configuration: what gio dev runs (.env.development*, the ephemeral session secret). |
--prod | boolean | - | Check the production configuration: what gio start runs. A production-only problem is an error, even when NODE_ENV is unset. |
--json | boolean | false | Print { ok, mode, environment, checks } instead of the report (see JSON output). |
-h, --help | boolean | - | Print the help and exit with 0. |
--dev and --prod together are a usage error. Without either, NODE_ENV decides, as it does for the server: development when it is development, production otherwise. When production is only assumed because NODE_ENV is unset (or something else), problems that gio dev would not have are warnings, not errors.
Checks
| Id | Checks | Fails (error) when |
|---|---|---|
node | The Node.js version | Older than GioJS needs (>=20). Outside your package.json engines is a warning. |
binary | The server binary in use | None is found; the detail names the package for this platform and how to install it. |
versions | @gio.js/server, its platform binary, @gio.js/core, @gio.js/react | @gio.js/core is missing, or the server, binary and core are not one version. A different @gio.js/react is a warning. |
app | The app/ directory | It does not exist (run from the project root or set GIO_APP_DIR). |
config | gio.toml, validated by the server binary itself through --check-config | The server would refuse to start. Protections the file turns off are warnings, with the server's own text. |
tsconfig | tsconfig.json or jsconfig.json | Never: missing .gio/routes.d.ts in include is a warning. |
session | GIO_SESSION_SECRET for require_session guards (in gio.toml or middleware.ts) | The secret is invalid (each comma-separated secret needs 32 bytes), or guards exist and it is unset in production. Development uses an ephemeral secret (info). |
port | Whether the listen address can be bound | Never: in use, a privileged port or no IPv6 are warnings. |
proxy | [server] trusted_proxies | Never: deploy files (Dockerfile, fly.toml, Procfile, nginx.conf, ...) or rate limits with no trusted proxy give a hint. |
cache | The page cache directory | It (or its nearest existing parent) is not writable. |
Each check has a status: ✓ ok, i info (a hint), ! warn, ✗ error, - skipped. A skipped check says why in its title. The config check is skipped when no binary of the CLI's own version is available (a different version may not know the flag); the other checks then read gio.toml leniently. That reader follows dotted keys and inline tables as the server does (env.files = false and env = { files = false } turn the .env files off just like [env] files = false), and still fails the config check on an invalid GIO_ENV_FILES, with the server's own error. When it cannot read gio.toml either (a line that is not TOML, such as an unclosed [server header), the config check warns with the line numbers, and the session, port, proxy and cache checks are skipped with gio.toml could not be read (see above) instead of running on defaults.
When the server cannot read the configuration at all (gio.toml does not parse, or a .env file or GIO_ENV_FILES is invalid), the config check fails with the error, and the session, port, proxy and cache checks are skipped: - Session guards not checked: the server could not read the configuration (error above). They never pass on settings nobody could read. A configuration that parses but fails a later check (a missing TLS certificate) still gets them.
Output
$ npx gio doctor --prod
GioJS doctor
gio 0.1.0-beta.8
Node.js 22.22.0
Platform linux-x64 (glibc), 6.8.0-45-generic
Package manager npm
Server binary 0.1.0-beta.8 (/home/me/shop/node_modules/@gio.js/server-linux-x64/bin/giojs-server)
@gio.js/server 0.1.0-beta.8
@gio.js/core 0.1.0-beta.8
@gio.js/react 0.1.0-beta.8
create-giojs not installed
Project /home/me/shop
gio.toml gio.toml
NODE_ENV (unset)
Checking the production configuration (what `gio start` runs), as --prod asked.
✓ Node.js 22.22.0 (GioJS needs >=20)
✓ Server binary: @gio.js/server-linux-x64 0.1.0-beta.8
✓ @gio.js packages in lockstep (0.1.0-beta.8)
✓ App directory: /home/me/shop/app
✓ gio.toml is valid
✓ tsconfig.json includes .gio/routes.d.ts (typed routes)
✗ require_session guards exist but GIO_SESSION_SECRET is not set
In production every guarded request is denied until a secret is configured.
fix: Set GIO_SESSION_SECRET in the deploy environment. Generate one: node -e "console.log(require('crypto').randomBytes(32).toString('base64url'))"
✓ Port 3000 is free (0.0.0.0:3000, from gio.toml)
i Behind a reverse proxy or load balancer? Set [server] trusted_proxies
deploy files found (Dockerfile); 1 rate limit rule(s) key on the client IP. Without it X-Forwarded-For/-Proto are ignored, so every request appears to come from the proxy: rate limits share one bucket and logs show the proxy address.
fix: In gio.toml: [server] trusted_proxies = ["10.0.0.0/8"] (your proxy's address or CIDR block)
✓ Cache directory is writable (/home/me/shop/.gio/cache/pages)
1 error, 0 warnings.The environment half is the same report as gio info.
JSON output
| Field | Type | Default | Description |
|---|---|---|---|
ok | boolean | - | false when any check has status error. |
mode | object | - | The configuration checked: name is development or production, explicit is false when production was assumed, source is --dev, --prod, NODE_ENV or null. |
environment | object | - | The gio info --json report. |
checks | object[] | - | One { id, status, title, detail?, fix? } per check, in the order above. status is ok, info, warn, error or skip. |
{
"ok": false,
"mode": { "name": "production", "explicit": true, "source": "--prod" },
"environment": { "gio": "0.1.0-beta.8", "node": "22.22.0", "...": "..." },
"checks": [
{
"id": "session",
"status": "error",
"title": "require_session guards exist but GIO_SESSION_SECRET is not set",
"detail": "In production every guarded request is denied until a secret is configured.",
"fix": "Set GIO_SESSION_SECRET in the deploy environment. ..."
}
]
}Examples
Gate a deploy
npx gio doctor --prod || exit 1Run it in the deploy environment, with its variables set: it fails on a missing session secret, an invalid gio.toml, mismatched package versions or a missing binary.
Check what gio dev will see
npx gio doctor --devAttach to a bug report
npx gio doctor --json > doctor.jsonSecrets never appear: the session secret is reported only as set, unset or invalid.
Good to know
- Exit codes:
0when no check has statuserror(warnings and hints do not fail),1when one does,2for a usage error. - The listen address is the one the server would use:
GIO_PORT/PORT/GIO_HOST, the.envfiles, thengio.toml. A port in use is only a warning, because it is often your own running server. - The package manager is the one running
gio(fromnpm_config_user_agent), else the one whose lockfile the project has; the fixes use its commands. gio doctordoes not loadgio.config.tsor import your modules. A broken plugin or aroute.tsthat throws shows up ingio routesand at startup.
Related
giojs-server --check-config- the server-side halfgio info- Production Checklist
- Authentication & Sessions
Version history
| Version | Changes |
|---|---|
v0.1.0-beta.8 | Introduced, with --dev, --prod and --json. The config check reports the warnings for protections gio.toml turns off. Checks that need a configuration the server could not read are skipped with the reason, instead of passing. |