Troubleshooting
The issues you are most likely to hit in production, and how to resolve them.
Common issues
Authentication failures
Authentication issues come in two forms: requests that cannot be verified at all, and requests with credentials that lack the right permissions.
Missing or invalid tokens
A 401 Unauthorized, or "Authentication required" and "Invalid or expired token" in your logs, means the request arrived without a token the gateway can verify: a missing Authorization header, an expired or revoked token, or a malformed Bearer header.
Check what the client is actually sending. The header should look like this:
Authorization: Bearer YOUR_TOKENIf the header looks right, open the Web UI and go to Tokens to confirm the token exists and has not been revoked or expired. If it is stale, create a replacement there and revoke the old one.
When several clients fail at once, the pattern tells you where to look. A cluster of failures from one integration usually points to a deployment shipped with an outdated token, while failures spread across many clients suggest a change on the gateway side.
Security Best Practice
Tokens are API keys. Storing them in environment variables or a dedicated secret manager, and keeping them out of version control, is recommended.
Insufficient token permissions
A 403 Forbidden means the token is valid but not allowed to do what the request asks. The logs show "Access denied to endpoint" or "Access denied to environment". Either the token lacks the scope for that endpoint, or it does not cover the environment being reached.
You can inspect what a token is allowed to do directly from its file:
Then compare that against what the endpoint configuration expects:
{
"AllowedEnvironments": ["prod", "dev"],
"AllowedScopes": "Products,Orders"
}If the access is legitimate, edit the token in the Web UI under Tokens to add the missing scopes or environments.
Rate limiting issues
429 Too Many Requests, or "Rate limit exceeded" and "IP blocked" in the logs, means someone is sending more requests than the configured thresholds allow. That can be genuine high-volume usage, integration testing, or a retry loop without backoff.
Start by checking what the current limits actually are:
{
"RateLimiting": {
"Enabled": true,
"IpLimit": 100,
"IpWindow": 60,
"TokenLimit": 1000,
"TokenWindow": 60
}
}Then look at who is hitting them:
If the pattern is isolated to one client or IP, exponential backoff in their retry logic fixes it at the source. If legitimate usage has outgrown the thresholds, raising the limits is the better answer.
For immediate relief during an incident, restarting Portway resets all counters:
A note on restarts
Rate limiting uses in-memory token buckets, so restarting resets every counter to zero. That helps in an emergency, but it is not a fix if clients consistently hit limits. Follow up on the request pattern or the configuration.
Connection issues
When your database won't connect
Database connection failures show up as 500 Internal Server Error on SQL endpoints, when the gateway cannot reach your database or the connection drops.
First verify the connection string is correct and complete:
{
"ConnectionString": "Server=YOUR_SERVER;Database=500;Trusted_Connection=True;Connection Timeout=15;TrustServerCertificate=true;"
}Then test whether the gateway server can reach the database at all:
If basic connectivity works but failures persist, a pool that is too small for your traffic shows up as intermittent errors. The SqlConnectionPooling properties and their defaults are in Application Settings.
When proxy endpoints stop responding
Failing proxy endpoints surface as timeout errors, "Error processing endpoint" messages, or 503 Service Unavailable. This is common with legacy backends where availability is not guaranteed.
Test whether the target service is reachable directly:
If the direct connection works, check the proxy configuration for the URL and settings:
{
"Url": "http://localhost:8020/services/Exact.Entity.REST.EG/Account",
"Methods": ["GET", "POST"],
"AllowedEnvironments": ["prod", "dev"]
}Environment settings are worth a look too, since they carry what the backend expects:
Health check failures
When you're running out of disk space
Low storage shows as "Unhealthy" status with warnings about remaining disk space. Left alone it causes log write failures and eventually stops the application.
Check how much space is available:
Old log files are usually the quickest win, especially with traffic logging enabled:
For ongoing space management, configure rotation so it does not recur:
{
"RequestTrafficLogging": {
"MaxFileSizeMB": 50,
"MaxFileCount": 5
}
}When your backend services aren't responding
"One or more proxy services are not responding properly" means the gateway is fine but a backend it depends on is not.
Request a detailed health report to see which services are failing:
GET /health/details
Authorization: Bearer YOUR_TOKENThen test the problematic endpoints individually:
For endpoints that keep failing, check their error logs:
Performance issues
High latency, timeouts, or durations over 1000ms in the logs point to database bottlenecks, network issues, or resource constraints.
Enable detailed traffic logging to see where time is spent:
{
"RequestTrafficLogging": {
"Enabled": true,
"EnableInfoLogging": true
}
}With SQLite traffic logging you can query the slowest requests directly:
-- Find slow requests (using SQLite logging)
SELECT Path, QueryString, DurationMs, StatusCode
FROM TrafficLogs
WHERE DurationMs > 1000
ORDER BY DurationMs DESC
LIMIT 20;Database connection management is a frequent cause. If the pool is too small, requests wait for a free connection, and raising MaxPoolSize in SqlConnectionPooling is where to start. Queries cut off mid-run are a different problem: CommandTimeout bounds how long a single statement may run, so a query dying at exactly that mark needs either a higher timeout or a faster query.
Diagnostic tools
Understanding your log files
Where to find your logs
| Log Type | Default Location | What You'll Find Here |
|---|---|---|
| Application Logs | ./log/portwayapi-*.log |
General application events, errors, and startup information |
| Traffic Logs (File) | ./log/traffic/proxy_traffic_*.json |
Detailed request/response information in JSON format |
| Traffic Logs (SQLite) | ./log/traffic_logs.db |
Queryable database of all traffic for analysis |
| Auth Database | ./auth.db |
Token authentication data and user information |
Handy commands for log analysis
To find recent errors across all log files:
To see which errors are most common:
For real-time monitoring during active troubleshooting:
Database diagnostics
Checking authentication status
When a client reports authentication problems, verify their token status:
-- Using SQLite browser or command line
SELECT Id, Username, CreatedAt, ExpiresAt, AllowedScopes, AllowedEnvironments
FROM Tokens
WHERE RevokedAt IS NULL
ORDER BY CreatedAt DESC;Understanding traffic patterns and errors
The traffic logs database shows which endpoints carry the highest error rates:
-- Error distribution by endpoint
SELECT EndpointName,
COUNT(CASE WHEN StatusCode >= 400 THEN 1 END) as Errors,
COUNT(*) as TotalRequests,
ROUND(CAST(COUNT(CASE WHEN StatusCode >= 400 THEN 1 END) AS FLOAT) / COUNT(*) * 100, 2) as ErrorRate
FROM TrafficLogs
WHERE Timestamp > datetime('now', '-24 hours')
GROUP BY EndpointName
HAVING Errors > 0
ORDER BY ErrorRate DESC;Network and connectivity diagnostics
These tell you quickly whether the problem is basic connectivity or something inside the application:
Understanding error messages
Error codes
| Status | Message | Cause | Fix |
|---|---|---|---|
400 |
"Environment '' is not allowed" | The environment specified in your URL path isn't configured as valid for this endpoint | Check the allowed environments list in your endpoint's settings.json file |
403 |
"Access denied to endpoint" | Your token is valid but doesn't have permission to access this specific endpoint | Update the token's scopes in the Web UI under Tokens |
404 |
"Endpoint '' not found" | The gateway can't find a configuration file for the endpoint you're trying to access | Verify that the endpoint configuration file exists and is properly named |
429 |
"Too many requests" | You've exceeded the rate limits set for your IP address or token | Wait for the rate limit window to reset, or increase the limits in configuration |
500 |
"Database operation failed" | The gateway can't connect to or query the SQL Server database | Check your connection string and verify SQL Server is accessible |
| Blank | No content/blank page | Usually indicates TLS/SSL certificate issues | Bind a certificate in IIS, or check the TLS termination in front of the container |
Recognizing log message patterns
[INF] Rate limit enforced for {Identifier} - Someone hit the rate limits
[WRN] Tokens detected in the tokens directory. Relocate them to a secure location - Warning, take action
[ERR] Error processing endpoint {EndpointName} - Backend service issue
[DBG] SQL Query Request: {Url} - Database query being executedEmergency procedures
Application not starting
When the gateway will not start, the cause is usually at the infrastructure level rather than in the application. Start by asking the host what it saw:
If the host looks healthy but the application still won't start, check the application log for startup errors:
Complete system reset (use with extreme caution)
Emergency Only
Only perform these steps when you've exhausted other options and after creating proper backups. This procedure will reset your gateway to a clean state, which may resolve persistent issues but will also clear all temporary data.
Before doing anything drastic, create a complete backup of your critical configuration:
Once you have a backup, you can reset the application state:
After a reset, watch the application logs as it starts and test a few endpoints to confirm it came back cleanly.
Keeping it healthy
- Disk space. Alert below 20% free and clear old logs on a schedule. Traffic logging generates substantial volume.
- Health endpoints. Automate checks against
/healthplus a few real endpoints. The Telemetry guide covers feeding gateway metrics into an existing monitoring stack. - Backend connectivity. Verify SQL and proxy targets after network changes or server maintenance.
Portway