9.6 KiB
SatLoc API Error Patterns - Complete Reference
Date: October 3, 2025
Purpose: Document ALL actual SatLoc API error responses discovered through testing
Status: Based on real API testing with invalid credentials and parameters
Summary
The SatLoc API has THREE DISTINCT error patterns depending on the type of error:
- Authentication Errors (wrong username/password)
- Parameter Validation Errors (wrong IDs)
- Server Errors (internal failures)
CRITICAL: Do NOT confuse authentication errors with parameter validation errors!
1. Authentication Errors
Test Scenario: AuthenticateAPIUser with Wrong Credentials
Tested Cases:
- Wrong username and password
- Empty password
- SQL injection attempts
- Special characters in credentials
API Response Pattern:
HTTP Status: 400
Status Text: "Invalid Username or Password provide."
Response Body: "" (empty string, NOT JSON)
Content-Type: text/html; charset=utf-8
Example Test Result:
// Test: Wrong username and password
{
status: 400,
statusText: "Invalid Username or Password provide.",
data: "" // Empty string!
}
Detection Pattern:
function isAuthenticationError(error) {
const status = error.response?.status;
const statusText = error.response?.statusText || '';
const data = error.response?.data;
return status === 400 &&
data === '' &&
(statusText.includes('Invalid Username') ||
statusText.includes('Invalid Password'));
}
Handling Strategy:
- Clear authentication cache
- Wait 3 seconds (allow for credential propagation)
- Retry authentication ONCE with fresh credentials
- If retry fails, throw AppAuthError
- Worker should retry the task (not send to DLQ)
2. Parameter Validation Errors
Test Scenario: API Methods with Wrong IDs
Affected Endpoints:
GetAircraftList- with wrong userId or companyIdGetAircraftLogs- with wrong userId or aircraftId- Other data access endpoints
API Response Pattern:
HTTP Status: 400
Status Text: "Bad Request"
Response Body: { "message": "The request is invalid." }
Content-Type: application/json; charset=utf-8
Example Test Results:
// Test 1: GetAircraftList with wrong userId
{
status: 400,
statusText: "Bad Request",
data: {
"message": "The request is invalid."
}
}
// Test 2: GetAircraftList with wrong companyId
{
status: 400,
statusText: "Bad Request",
data: {
"message": "The request is invalid."
}
}
// Test 3: GetAircraftList with empty userId
{
status: 400,
statusText: "Bad Request",
data: {
"message": "The request is invalid."
}
}
// Test 4: GetAircraftLogs with wrong userId
{
status: 400,
statusText: "Bad Request",
data: {
"message": "The request is invalid."
}
}
// Test 5: GetAircraftLogs with wrong aircraftId
{
status: 400,
statusText: "Bad Request",
data: {
"message": "The request is invalid."
}
}
Detection Pattern:
function isParameterValidationError(error) {
const status = error.response?.status;
const statusText = error.response?.statusText || '';
const data = error.response?.data;
return status === 400 &&
typeof data === 'object' &&
data.message === 'The request is invalid.' &&
statusText === 'Bad Request';
}
Handling Strategy:
- Do NOT clear authentication cache (credentials are fine!)
- Do NOT retry (the IDs are wrong, retry won't help)
- Log error with context (which IDs are wrong)
- Return error to caller with clear message
- Worker should NOT retry (data issue, not transient)
IMPORTANT: These are NOT authentication errors! The credentials are valid, but the resource IDs (userId, companyId, aircraftId) don't exist or don't match.
3. Server Errors
Test Scenario: API Methods Triggering Server Failures
Affected Endpoints:
UploadJobData- with wrong userId/companyId/aircraftId- Potentially any endpoint under certain conditions
API Response Pattern:
HTTP Status: 500
Status Text: "Internal Server Error"
Response Body: "" (empty string)
Content-Type: text/html; charset=utf-8
Example Test Results:
// Test 6: UploadJobData with wrong userId and companyId
{
status: 500,
statusText: "Internal Server Error",
data: "" // Empty string!
}
// Test 7: UploadJobData with wrong aircraftId
{
status: 500,
statusText: "Internal Server Error",
data: "" // Empty string!
}
Special Case - Empty Username in Authentication:
// Test: AuthenticateAPIUser with empty username
{
status: 500,
statusText: "Internal Server Error",
data: {
"message": "An error has occurred."
}
}
Detection Pattern:
function isServerError(error) {
const status = error.response?.status;
return status >= 500;
}
Handling Strategy:
- Log error with full context
- Do NOT clear authentication cache (server issue, not credentials)
- Allow worker to retry with exponential backoff
- If persistent, send alert to monitoring
- May be transient (server restart, network issue, etc.)
Error Decision Tree
Is error.response.status === 400?
├─ YES: Is response.data an empty string?
│ ├─ YES: Does statusText contain "Invalid Username" or "Invalid Password"?
│ │ ├─ YES: → AUTHENTICATION ERROR
│ │ └─ NO: → Unknown 400 error
│ └─ NO: Is response.data.message === "The request is invalid."?
│ ├─ YES: → PARAMETER VALIDATION ERROR
│ └─ NO: → Unknown 400 error
└─ NO: Is error.response.status >= 500?
├─ YES: → SERVER ERROR
└─ NO: → Check other status codes (401, 403, 404, etc.)
Implementation in Code
isAuthError() Method
/**
* Check if error is authentication-related (wrong credentials)
* NOT parameter validation (wrong IDs)
*/
isAuthError(error) {
if (!error) return false;
// Check if error is AppAuthError (thrown by our authenticate() method)
if (error.name === 'AppAuthError' || error.constructor.name === 'AppAuthError') {
return true;
}
const status = error.response?.status;
const statusText = (error.response?.statusText || '').toLowerCase();
const responseData = error.response?.data;
// Authentication endpoint failure: HTTP 400 + empty string + specific statusText
if (status === 400 && responseData === '' &&
(statusText.includes('invalid username') ||
statusText.includes('invalid password') ||
statusText.includes('username or password'))) {
return true;
}
// NOTE: HTTP 400 with JSON response {"message": "The request is invalid."}
// is NOT an auth error - it's parameter validation (wrong IDs)
// Check error message from our code
const message = (error.message || '').toLowerCase();
if (message.includes('authentication failed') ||
message.includes('wrong_credential') ||
message.includes('invalid credential')) {
return true;
}
return false;
}
Error Handling in API Methods
async getAircraftList(customerId) {
try {
const authData = await this.getCachedAuth(customerId);
const response = await axios.get(
`${this.config.apiEndpoint}/GetAircraftList`,
{
params: {
userId: authData.userId,
companyId: authData.companyId
},
...this.requestConfig
}
);
return {
success: true,
aircraft: response.data || []
};
} catch (error) {
const status = error.response?.status;
const data = error.response?.data;
let errorMessage = error.message;
// Provide specific error messages based on error type
if (status === 400 && typeof data === 'object' && data.message) {
errorMessage = `Invalid parameters: ${data.message} (check userId/companyId)`;
} else if (status >= 500) {
errorMessage = `SatLoc server error: ${error.message}`;
} else if (this.isAuthError(error)) {
errorMessage = `Authentication failed: ${error.message}`;
}
pino.debug('SatLoc GetAircraftList failed',
`customer=${customerId}, status=${status}, error=${errorMessage}`);
return {
success: false,
error: errorMessage,
isAuthError: this.isAuthError(error),
isServerError: status >= 500
};
}
}
Testing Commands
Test Authentication Errors
node tests/test_satloc_errors_simple.js
Test All API Endpoints with Invalid Data
node tests/test_satloc_all_endpoints.js
Key Takeaways
-
HTTP 400 does NOT always mean authentication error!
- Empty string response + specific statusText = Authentication error
- JSON response with "The request is invalid." = Parameter validation error
-
Parameter validation errors should NOT trigger cache clearing
- The credentials are valid
- The resource IDs are wrong
- Retrying won't help
-
Server errors (HTTP 500) may be transient
- Allow worker retry with backoff
- Monitor for persistent failures
-
Always check response body type and content
- Empty string vs JSON object changes the meaning
- statusText provides additional context
-
Test with actual API calls, not assumptions!
- "Standard" REST patterns don't always apply
- Each API has its own error conventions
References
- Test script:
test_satloc_errors_simple.js- Authentication errors - Test script:
test_satloc_all_endpoints.js- All endpoint errors - Implementation:
services/satloc_service.js- Error detection and handling - Documentation:
docs/SATLOC_API_ACTUAL_BEHAVIOR.md- Authentication endpoint behavior