{
  "name": "Fix Erreur 422 Mistral API",
  "nodes": [
    {
      "parameters": {},
      "id": "start-fix-422",
      "name": "Start",
      "type": "n8n-nodes-base.start",
      "typeVersion": 1,
      "position": [
        240,
        300
      ]
    },
    {
      "parameters": {
        "jsCode": "// CR\u00c9ATION D'UN PAYLOAD MISTRAL EXPLICITE ET VALID\u00c9\nconsole.log('\ud83d\udd27 === CR\u00c9ATION PAYLOAD MISTRAL S\u00c9CURIS\u00c9 ===');\n\n// Donn\u00e9es de test simples pour diagnostiquer l'erreur 422\nconst testData = {\n  id: 'test-422-fix',\n  title: 'Contrat apprentissage - Analyste Cybers\u00e9curit\u00e9',\n  company: 'Test Company',\n  description: 'Poste en cybers\u00e9curit\u00e9 pour alternance.',\n  contract_type: 'Apprentissage'\n};\n\n// Construction explicite du payload selon les sp\u00e9cifications Mistral\nconst mistralPayload = {\n  \"model\": \"mistral-large-latest\",\n  \"messages\": [\n    {\n      \"role\": \"system\",\n      \"content\": \"Tu es un expert RH sp\u00e9cialis\u00e9 en cybers\u00e9curit\u00e9.\"\n    },\n    {\n      \"role\": \"user\",\n      \"content\": `Analyse cette offre: ${testData.title}. Type: ${testData.contract_type}. R\u00e9ponds par VALIDE ou INVALIDE.`\n    }\n  ],\n  \"temperature\": 0.1,\n  \"max_tokens\": 200\n};\n\n// Validation stricte du payload\nfunction validateMistralPayload(payload) {\n  const errors = [];\n  \n  // V\u00e9rification du mod\u00e8le\n  if (!payload.model || typeof payload.model !== 'string') {\n    errors.push('Model manquant ou invalide');\n  }\n  \n  // V\u00e9rification des messages\n  if (!payload.messages) {\n    errors.push('Messages manquants');\n  } else if (!Array.isArray(payload.messages)) {\n    errors.push('Messages doit \u00eatre un array');\n  } else if (payload.messages.length === 0) {\n    errors.push('Au moins un message requis');\n  } else {\n    payload.messages.forEach((msg, index) => {\n      if (!msg.role || typeof msg.role !== 'string') {\n        errors.push(`Message ${index}: role manquant/invalide`);\n      }\n      if (!msg.content || typeof msg.content !== 'string') {\n        errors.push(`Message ${index}: content manquant/invalide`);\n      }\n      if (!['system', 'user', 'assistant'].includes(msg.role)) {\n        errors.push(`Message ${index}: role invalide (${msg.role})`);\n      }\n    });\n  }\n  \n  // V\u00e9rification des param\u00e8tres optionnels\n  if (payload.temperature !== undefined) {\n    if (typeof payload.temperature !== 'number' || payload.temperature < 0 || payload.temperature > 2) {\n      errors.push('Temperature doit \u00eatre un nombre entre 0 et 2');\n    }\n  }\n  \n  if (payload.max_tokens !== undefined) {\n    if (!Number.isInteger(payload.max_tokens) || payload.max_tokens < 1) {\n      errors.push('Max_tokens doit \u00eatre un entier positif');\n    }\n  }\n  \n  return {\n    isValid: errors.length === 0,\n    errors,\n    payload\n  };\n}\n\nconst validation = validateMistralPayload(mistralPayload);\n\nconsole.log('\u2705 Validation payload:', validation.isValid);\nif (!validation.isValid) {\n  console.log('\u274c Erreurs de validation:', validation.errors);\n  throw new Error(`Payload invalide: ${validation.errors.join(', ')}`);\n}\n\nconsole.log('\ud83d\udccb Payload Mistral final:', JSON.stringify(mistralPayload, null, 2));\nconsole.log('\ud83d\udccf Taille JSON:', JSON.stringify(mistralPayload).length, 'caract\u00e8res');\n\nreturn {\n  json: {\n    test_data: testData,\n    mistral_payload: mistralPayload,\n    validation_result: validation,\n    payload_json_string: JSON.stringify(mistralPayload),\n    created_at: new Date().toISOString()\n  }\n};"
      },
      "id": "payload-builder",
      "name": "\ud83d\udd27 Construction Payload",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        460,
        300
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.mistral.ai/v1/chat/completions",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "Authorization",
              "value": "Bearer fe8GdBIIBwYk8Dj1GvclASPE3j0Zbt95"
            },
            {
              "name": "Content-Type",
              "value": "application/json"
            },
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "sendBody": true,
        "contentType": "raw",
        "body": "={{ $json.payload_json_string }}",
        "options": {
          "timeout": 30000
        }
      },
      "id": "mistral-api-test",
      "name": "\ud83c\udf10 Test API Mistral",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        680,
        300
      ],
      "onError": "continueErrorOutput"
    },
    {
      "parameters": {
        "jsCode": "// ANALYSE DU SUCC\u00c8S DE L'APPEL API\nconst requestData = $input.first().json;\nconst apiResponse = $input.last().json;\n\nconsole.log('\u2705 === SUCC\u00c8S API MISTRAL ===');\nconsole.log('\ud83d\udce5 Status: R\u00e9ponse re\u00e7ue avec succ\u00e8s');\nconsole.log('\ud83d\udd11 Request ID:', requestData.test_data.id);\n\n// Validation de la structure de r\u00e9ponse\nif (!apiResponse || !apiResponse.choices || apiResponse.choices.length === 0) {\n  console.log('\u26a0\ufe0f Structure de r\u00e9ponse inattendue');\n  return {\n    json: {\n      ...requestData,\n      api_response: apiResponse,\n      status: 'SUCCESS_BUT_UNEXPECTED_STRUCTURE',\n      analysis: 'R\u00e9ponse re\u00e7ue mais structure non standard'\n    }\n  };\n}\n\nconst messageContent = apiResponse.choices[0].message?.content || 'Pas de contenu';\n\nconsole.log('\ud83d\udcdd R\u00e9ponse Mistral:', messageContent.substring(0, 100) + '...');\nconsole.log('\ud83d\udd27 Mod\u00e8le utilis\u00e9:', apiResponse.model);\nconsole.log('\ud83d\udcca Usage tokens:', JSON.stringify(apiResponse.usage || {}));\n\n// Analyse de la classification\nlet classification = 'IND\u00c9TERMIN\u00c9';\nif (messageContent.toUpperCase().includes('VALIDE')) {\n  classification = 'VALIDE';\n} else if (messageContent.toUpperCase().includes('INVALIDE')) {\n  classification = 'INVALIDE';\n}\n\nreturn {\n  json: {\n    ...requestData,\n    api_response: apiResponse,\n    status: 'SUCCESS',\n    classification: classification,\n    message_content: messageContent,\n    model_used: apiResponse.model,\n    usage: apiResponse.usage,\n    processed_at: new Date().toISOString(),\n    success_analysis: {\n      payload_was_valid: true,\n      api_responded: true,\n      classification_extracted: classification !== 'IND\u00c9TERMIN\u00c9',\n      error_422_resolved: true\n    }\n  }\n};"
      },
      "id": "success-handler",
      "name": "\u2705 Succ\u00e8s API",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        200
      ]
    },
    {
      "parameters": {
        "jsCode": "// ANALYSE D\u00c9TAILL\u00c9E DE L'ERREUR 422\nconst requestData = $input.first().json;\nconst errorData = $input.last();\n\nconsole.log('\u274c === ANALYSE ERREUR 422 MISTRAL ===');\nconsole.log('\ud83d\udd0d Erreur compl\u00e8te:', JSON.stringify(errorData, null, 2));\n\n// Extraction des d\u00e9tails d'erreur\nconst errorDetails = {\n  http_code: errorData.httpCode || 'N/A',\n  error_message: errorData.message || 'Pas de message',\n  error_name: errorData.name || 'Erreur inconnue',\n  error_details: errorData.details || {},\n  timestamp: new Date().toISOString()\n};\n\n// Analyse sp\u00e9cifique de l'erreur 422\nlet rootCause = 'UNKNOWN';\nlet suggestedFix = 'Analyser manuellement';\nlet canRetry = false;\n\nif (errorDetails.http_code === 422) {\n  console.log('\ud83c\udfaf Erreur 422 confirm\u00e9e - Analyse des causes...');\n  \n  const errorText = errorDetails.error_message.toLowerCase();\n  \n  if (errorText.includes('messages') && errorText.includes('required')) {\n    rootCause = 'MISSING_MESSAGES_FIELD';\n    suggestedFix = 'Le champ messages est manquant dans le payload';\n  } else if (errorText.includes('model') && errorText.includes('required')) {\n    rootCause = 'MISSING_MODEL_FIELD';\n    suggestedFix = 'Le champ model est manquant dans le payload';\n  } else if (errorText.includes('invalid') && errorText.includes('format')) {\n    rootCause = 'INVALID_FORMAT';\n    suggestedFix = 'Format JSON du payload invalide';\n  } else if (errorText.includes('field required')) {\n    rootCause = 'REQUIRED_FIELD_MISSING';\n    suggestedFix = 'Un champ obligatoire est manquant';\n  }\n  \n  canRetry = rootCause !== 'UNKNOWN';\n}\n\n// Debug du payload envoy\u00e9\nconsole.log('\ud83d\udccb Payload envoy\u00e9:', requestData.payload_json_string);\nconsole.log('\ud83d\udd0d Validation pr\u00e9-envoi:', JSON.stringify(requestData.validation_result, null, 2));\n\n// Analyse comparative\nconst diagnostics = {\n  payload_size: requestData.payload_json_string.length,\n  payload_valid_json: isValidJSON(requestData.payload_json_string),\n  has_model_field: requestData.payload_json_string.includes('\"model\"'),\n  has_messages_field: requestData.payload_json_string.includes('\"messages\"'),\n  messages_is_array: requestData.payload_json_string.includes('\"messages\":['),\n  request_headers_correct: true // On assume que les headers sont corrects\n};\n\nfunction isValidJSON(str) {\n  try {\n    JSON.parse(str);\n    return true;\n  } catch (e) {\n    return false;\n  }\n}\n\nconsole.log('\ud83d\udd2c Diagnostics:', JSON.stringify(diagnostics, null, 2));\n\n// G\u00e9n\u00e9ration du rapport d'erreur complet\nconst errorReport = {\n  error_type: 'API_422_ERROR',\n  root_cause: rootCause,\n  suggested_fix: suggestedFix,\n  can_retry: canRetry,\n  error_details: errorDetails,\n  diagnostics: diagnostics,\n  original_payload: requestData.mistral_payload,\n  payload_string: requestData.payload_json_string,\n  investigation_steps: [\n    '1. V\u00e9rifier que le payload contient le champ messages',\n    '2. V\u00e9rifier que messages est un array',\n    '3. V\u00e9rifier que chaque message a role et content',\n    '4. V\u00e9rifier que le JSON est valide',\n    '5. V\u00e9rifier les headers HTTP'\n  ]\n};\n\nreturn {\n  json: {\n    ...requestData,\n    status: 'ERROR_422',\n    error_report: errorReport,\n    next_actions: canRetry ? ['RETRY_WITH_CORRECTED_PAYLOAD'] : ['MANUAL_INVESTIGATION']\n  }\n};\n\nfunction isValidJSON(str) {\n  try {\n    JSON.parse(str);\n    return true;\n  } catch (e) {\n    return false;\n  }\n}"
      },
      "id": "error-422-analyzer",
      "name": "\ud83d\udd0d Analyse Erreur 422",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        900,
        400
      ]
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "result-assignment",
              "name": "final_result",
              "value": "={{ $json }}",
              "type": "object"
            },
            {
              "id": "status-assignment",
              "name": "execution_status",
              "value": "Ex\u00e9cution termin\u00e9e - Status: {{ $json.status }}",
              "type": "string"
            }
          ]
        },
        "options": {}
      },
      "id": "final-result",
      "name": "\ud83d\udcca R\u00e9sultat Final",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        1120,
        300
      ]
    }
  ],
  "connections": {
    "Start": {
      "main": [
        [
          {
            "node": "\ud83d\udd27 Construction Payload",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd27 Construction Payload": {
      "main": [
        [
          {
            "node": "\ud83c\udf10 Test API Mistral",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83c\udf10 Test API Mistral": {
      "main": [
        [
          {
            "node": "\u2705 Succ\u00e8s API",
            "type": "main",
            "index": 0
          }
        ]
      ],
      "error": [
        [
          {
            "node": "\ud83d\udd0d Analyse Erreur 422",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\u2705 Succ\u00e8s API": {
      "main": [
        [
          {
            "node": "\ud83d\udcca R\u00e9sultat Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "\ud83d\udd0d Analyse Erreur 422": {
      "main": [
        [
          {
            "node": "\ud83d\udcca R\u00e9sultat Final",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1",
    "saveManualExecutions": true,
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "fix-422-v1",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "id": "workflow-fix-422-mistral",
  "tags": [
    "debug",
    "mistral",
    "api",
    "422"
  ]
}