Troubleshooting
Status codes
| Status | Message | Cause | Resolution |
|---|---|---|---|
400 |
"Environment '' is not allowed" | The environment is not routable for the endpoint | Add it to AllowedEnvironments in environments/settings.json and the endpoint's entity.json |
400 |
"Header is required" | Tenant endpoint, token with several tenant values, header missing | Send the tenant header |
401 |
"Invalid or expired token" | Missing, malformed, expired or archived token | Check the Authorization header and the token under Access Tokens |
403 |
"Access denied to endpoint" / "to environment" | Token scopes or environments exclude the request | Edit the token under Access Tokens |
403 |
Tenant access refused | Token has no value for the tenant header, or the header names another value | Add the value to the token's tenants |
404 |
"Endpoint '' not found" | No loaded endpoint configuration for the path | Check the file path and the startup log for load errors |
429 |
"Too many requests" | IP or token rate limit exceeded | Wait for Retry-After, or adjust the limits |
500 |
"A data error occurred" | Database unreachable or query failure | Check the connection string and database access; the log entry has the reference id |
| none | Blank page | TLS certificate problem | Bind a certificate in IIS or check TLS termination in front of the container |
Authentication
A 401 means the token could not be verified. The header format:
Authorization: Bearer YOUR_TOKENCheck under Access Tokens that the token exists and is neither expired nor archived. Failures from one integration indicate an outdated token in that deployment. Failures across many clients indicate a gateway change.
A 403 means the token is valid but its scopes, environments or tenants exclude the request. Compare the token's scopes and environments under Access Tokens with the endpoint's AllowedEnvironments and the scope patterns.
Rate limiting
Rate limit events in the log:
A single client hitting the limit requires backoff in its retry logic or its own token limit. Limits and stores: Rate Limiting.
Database connections
SQL endpoints return 500 when the database is unreachable.
Connectivity test from the gateway host:
Intermittent failures under load indicate an undersized pool (MaxPoolSize). Queries that stop at exactly CommandTimeout need a higher timeout or a faster query. Settings: SqlConnectionPooling.
Proxy endpoints
Unreachable upstreams return timeouts, "Error processing endpoint" or 503. Direct test from the gateway host:
When the direct request succeeds, compare the endpoint's Url and the environment's settings.json headers with what the upstream expects. Blocked hosts: Network access policy.
Health checks
The detailed health check (GET /health/details, with a token) names the failing check. The startup log lists unhealthy proxy endpoints in one Health check status: Unhealthy proxy endpoints detected warning; the reason per endpoint is logged at Debug.
Disk space
Low disk space reports Unhealthy and eventually stops log writes:
Traffic log rotation is set by RequestTrafficLogging:MaxFileSizeMB and MaxFileCount (Auditing).
Performance
Durations above 1000ms indicate a database, network or host problem. Slow request queries: SQLite storage.
Logs
| Log | Location | Contents |
|---|---|---|
| Application | ./log/portwayapi-*.log |
Startup, errors and events |
| Traffic (file) | ./log/traffic/proxy_traffic_*.json |
Per-request metadata |
| Traffic (SQLite) | ./log/traffic_logs.db |
Queryable per-request metadata |
| Authentication | ./auth.db |
Tokens, accounts and audits |
Recent errors and a live tail:
Log levels: Health and Logs.
Application not starting
Host state and startup output:
Startup errors in the application log:
Portway