Skip to main content

Overview

Kontrak Backend uses structured error responses to help you identify and resolve issues quickly. All errors follow a consistent format and include detailed information for debugging.

Error Response Structure

All API errors return a JSON response with the following structure:
{
  "success": false,
  "message": "Error description",
  "data": {
    // Additional error context (optional)
  },
  "errors": "Error details" // For internal errors
}

HTTP Status Codes

The API uses standard HTTP status codes defined in src/constants/http.ts:
Status CodeConstantMeaningWhen Used
200OKSuccessSuccessful requests
201CREATEDCreatedResource created successfully
400BAD_REQUESTBad RequestInvalid input or validation errors
401UNAUTHORIZEDUnauthorizedAuthentication required
403FORBIDDENForbiddenInsufficient permissions
404NOT_FOUNDNot FoundResource not found
409CONFLICTConflictResource conflict
422UNPROCESSABLE_CONTENTUnprocessableSemantic errors
429TOO_MANY_REQUESTSRate LimitedToo many requests
500INTERNAL_SERVER_ERRORServer ErrorUnexpected server error

Error Types

Application Errors (AppError)

Structured errors with specific status codes and context:
export class AppError extends Error {
  public readonly statusCode: number;
  public readonly data: AppErrorContext | undefined;
  
  constructor(
    message: string,
    statusCode: HttpStatusCode,
    data?: AppErrorContext,
  ) {
    super(message);
    this.statusCode = statusCode;
    this.data = data;
  }
}
Example Usage:
throw new AppError(
  'El archivo Excel no contiene datos válidos',
  BAD_REQUEST
);

Validation Errors

Validation errors include detailed information about which fields failed validation:
{
  "success": false,
  "message": "No se pudo procesar el archivo. Se encontraron 3 errores.",
  "data": {
    "validationErrors": [
      {
        "row": 2,
        "field": "dni",
        "message": "DNI debe tener exactamente 8 dígitos numéricos."
      },
      {
        "row": 3,
        "field": "email",
        "message": "Invalid email"
      },
      {
        "row": 5,
        "field": "salary",
        "message": "El sueldo debe ser mayor a 0"
      }
    ]
  }
}
Source: src/services/excel-parser.service.ts:58
const cleansErrors = validation.errors.map((err) => ({
  row: err.row,
  field: err.field,
  message: err.error.message,
}));

throw new AppError(
  `No se pudo procesar el archivo. Se encontraron ${validation.errors.length} errores.`,
  BAD_REQUEST,
  { validationErrors: cleansErrors },
);

File Upload Errors (Multer)

File upload errors are handled by the Multer middleware (src/middlewares/error-handler-multer.middleware.ts):
Status Code: 400Response:
{
  "success": false,
  "message": "El archivo es demasiado grande. Tamaño máximo: 10 MB"
}
Solution:
  • Reduce file size
  • Split data into multiple files
  • Increase MAX_FILE_SIZE in configuration
Status Code: 400Response:
{
  "success": false,
  "message": "Solo puedes subir 1 archivo a la vez"
}
Solution:
  • Upload one file at a time
  • Combine data into single Excel file
Status Code: 400Response:
{
  "success": false,
  "message": "Campo de archivo inesperado. Usa el campo 'excel'"
}
Solution:
  • Use field name excel for file upload
  • Check multipart form field name
Status Code: 400Response:
{
  "success": false,
  "message": "Tipo de archivo no permitido"
}
Solution:
  • Use .xlsx file format
  • Convert .xls files to .xlsx
  • Ensure proper MIME type

Common Error Scenarios

Excel File Errors

Error:
{
  "success": false,
  "message": "La estructura del archivo es incorrecta. Faltan columnas obligatorias.",
  "data": {
    "validationErrors": [
      {
        "row": 1,
        "field": "dni",
        "message": "Encabezado requerido no encontrado en el archivo."
      }
    ]
  }
}
Debugging Steps:
  1. Check first row contains headers
  2. Verify header spelling matches accepted aliases
  3. Remove extra spaces in header names
  4. Check for special characters in headers
Solution:
  • Add missing column headers
  • Use one of the accepted aliases from field configuration
  • See Excel Upload Guide for valid headers

Validation Errors

Common Errors:
{
  "row": 2,
  "field": "dni",
  "message": "DNI debe tener exactamente 8 dígitos numéricos."
}
Validation Rule:
dni: z.string()
  .regex(/^\d{8}$/, 'DNI debe tener exactamente 8 dígitos numéricos')
Valid Examples:
  • 12345678
  • 87654321
Invalid Examples:
  • 1234567 (too short)
  • 123456789 (too long)
  • 12-345-678 (contains dashes)
  • 12.345.678 (contains dots)

Contract Type Errors

SUBSIDIO contracts require additional fields that must be provided.
{
  "row": 6,
  "field": "replacementFor",
  "message": "El campo 'SUPLENCIA DE' es obligatorio para contratos de Subsidio"
}
Conditional Validation (src/validators/employee.validator.ts:142):
.superRefine((data, ctx) => {
  if (data.contractType === 'Subsidio') {
    if (!data.replacementFor) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: "El campo 'SUPLENCIA DE' es obligatorio para contratos de Subsidio",
        path: ['replacementFor'],
      });
    }
    if (!data.reasonForSubstitution) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        message: "El campo 'MOTIVO DE SUPLENCIA' es obligatorio para contratos de Subsidio",
        path: ['reasonForSubstitution'],
      });
    }
  }
})
Solution:

Session and Resource Errors

Error:
{
  "success": false,
  "message": "Sesión no encontrada: abc123",
  "data": null
}
Status Code: 404Causes:
  • Session expired or cleaned up
  • Invalid session ID
  • Session directory deleted
Solution:
  • Re-upload Excel file to create new session
  • Check FILE_CLEANUP_TIMEOUT configuration
  • Verify session ID is correct

Error Handler Middleware

The global error handler (src/middlewares/error-handle.middleware.ts) catches all errors:
export const errorHandler: ErrorRequestHandler = (
  error,
  _req: Request,
  res,
  _next: NextFunction,
) => {
  if (error instanceof AppError) {
    handlerAppError(res, error);
    return;
  }
  
  logger.error(`${error.stack || error.message}`);
  res.status(INTERNAL_SERVER_ERROR).json({
    success: false,
    message: 'Internal Server Error',
    errors: error.message,
  });
};

AppError Handling

const handlerAppError = (res: Response, error: AppError) => {
  res.status(error.statusCode).json({
    success: false,
    message: error.message,
    data: error.data || null,
  });
};

Debugging Tips

1

Check Error Response

Read the error message and status code:
curl -X POST http://localhost:3000/api/excel/upload \
  -F "[email protected]" \
  -v
Look for:
  • HTTP status code in response headers
  • success: false in JSON body
  • message field with error description
  • data field with additional context
2

Review Server Logs

Check server console for detailed error information:
# Look for error logs
tail -f logs/app.log
The logger outputs:
  • Error stack traces
  • Validation details
  • File processing steps
  • CORS blocking messages
3

Validate Input Data

Verify your input matches expected format:
  • Excel files: Check headers and data types
  • JSON requests: Validate against schema
  • File uploads: Verify size and format
  • Dates: Use DD/MM/YYYY format
4

Test with Minimal Data

Isolate the issue with minimal test case:
# Test with single employee
curl -X POST http://localhost:3000/api/contract/download-zip \
  -H "Content-Type: application/json" \
  -d '{"body": [/* single employee */]}'
5

Check Configuration

Verify environment configuration:
# Check configuration is loaded
cat .env

# Verify temp directory exists
ls -la temp/

# Check file permissions
ls -la temp/

Error Prevention

Input Validation

  • Validate data before upload
  • Use provided Excel templates
  • Check required fields are present
  • Test with small batches first

File Preparation

  • Use .xlsx format
  • Keep files under size limit
  • Remove unnecessary formatting
  • Verify headers match aliases

API Usage

  • Check response status codes
  • Handle errors gracefully
  • Implement retry logic for transient errors
  • Log errors for debugging

Configuration

  • Set appropriate file size limits
  • Configure CORS correctly
  • Monitor disk space for temp files
  • Set reasonable timeouts

HTTP Client Error Handling Examples

const uploadExcel = async (file) => {
  const formData = new FormData();
  formData.append('excel', file);
  
  try {
    const response = await fetch('http://localhost:3000/api/excel/upload', {
      method: 'POST',
      body: formData,
    });
    
    const data = await response.json();
    
    if (!response.ok || !data.success) {
      // Handle validation errors
      if (data.data?.validationErrors) {
        console.error('Validation errors:', data.data.validationErrors);
        // Display errors to user
      } else {
        console.error('Error:', data.message);
      }
      throw new Error(data.message);
    }
    
    return data.data;
  } catch (error) {
    console.error('Upload failed:', error);
    throw error;
  }
};

Next Steps

Configuration

Configure error handling and logging

Excel Upload

Learn proper Excel file format

Build docs developers (and LLMs) love