agmission/Development/server/docs/SATLOC_ERROR_PATTERNS.md

385 lines
9.6 KiB
Markdown

# 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:
1. **Authentication Errors** (wrong username/password)
2. **Parameter Validation Errors** (wrong IDs)
3. **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:**
```javascript
// Test: Wrong username and password
{
status: 400,
statusText: "Invalid Username or Password provide.",
data: "" // Empty string!
}
```
**Detection Pattern:**
```javascript
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 companyId
- `GetAircraftLogs` - 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:**
```javascript
// 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:**
```javascript
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:**
```javascript
// 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:**
```javascript
// Test: AuthenticateAPIUser with empty username
{
status: 500,
statusText: "Internal Server Error",
data: {
"message": "An error has occurred."
}
}
```
**Detection Pattern:**
```javascript
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
```javascript
/**
* 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
```javascript
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
```bash
node tests/test_satloc_errors_simple.js
```
### Test All API Endpoints with Invalid Data
```bash
node tests/test_satloc_all_endpoints.js
```
---
## Key Takeaways
1. **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
2. **Parameter validation errors should NOT trigger cache clearing**
- The credentials are valid
- The resource IDs are wrong
- Retrying won't help
3. **Server errors (HTTP 500) may be transient**
- Allow worker retry with backoff
- Monitor for persistent failures
4. **Always check response body type and content**
- Empty string vs JSON object changes the meaning
- statusText provides additional context
5. **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