Dépannage
Solutions aux problèmes courants et conseils de dépannage
Guide de Dépannage
Résolvez rapidement les problèmes les plus courants rencontrés avec Qwen Image Edit.
🔐 Erreurs d'Authentification
Clé API Invalide
Erreur : INVALID_API_KEY
Error: Invalid API key provided
Code: INVALID_API_KEY
Status: 401
Solutions :
-
Vérifiez votre clé API :
console.log('Clé API:', process.env.QWEN_API_KEY); // Assurez-vous qu'elle commence par 'qwen_' et fait 64 caractères
-
Vérifiez le fichier .env :
# .env QWEN_API_KEY=qwen_1234567890abcdef...
-
Régénérez votre clé :
- Connectez-vous au tableau de bord Qwen
- Allez dans "API Keys"
- Créez une nouvelle clé
- Mettez à jour votre configuration
Région Non Supportée
Erreur : UNSUPPORTED_REGION
Error: Region 'eu-central-1' is not supported
Code: UNSUPPORTED_REGION
Status: 400
Solution :
// Utilisez une région supportée
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
region: 'eu-west-1' // ✅ Supportée
// region: 'eu-central-1' // ❌ Non supportée
});
Régions supportées :
eu-west-1
(Irlande)us-east-1
(Virginie)ap-southeast-1
(Singapour)ap-northeast-1
(Tokyo)
📊 Problèmes de Quota et Limites
Quota Dépassé
Erreur : QUOTA_EXCEEDED
Error: Monthly quota exceeded. Upgrade your plan or wait for reset.
Code: QUOTA_EXCEEDED
Status: 429
Solutions :
-
Vérifiez votre quota actuel :
const quota = await editor.getQuotaInfo(); console.log('Quota utilisé:', quota.requestsUsed, '/', quota.requestsLimit); console.log('Reset le:', new Date(quota.resetDate));
-
Optimisez vos requêtes :
// Utilisez le cache pour éviter les requêtes dupliquées const editor = new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY, cache: { enabled: true, ttl: 3600 // 1 heure } });
-
Implémentez une gestion gracieuse :
try { const resultat = await editor.editText(options); } catch (error) { if (error.code === 'QUOTA_EXCEEDED') { console.log('Quota dépassé, programmation pour plus tard...'); // Programmer la requête pour après le reset const resetDate = new Date(error.resetDate); setTimeout(() => { // Réessayer la requête }, resetDate.getTime() - Date.now()); } }
Limite de Débit Atteinte
Erreur : RATE_LIMITED
Error: Rate limit exceeded. Try again in 60 seconds.
Code: RATE_LIMITED
Status: 429
Retry-After: 60
Solutions :
-
Implémentez un retry avec backoff :
import pRetry from 'p-retry'; async function editTextAvecRetry(options) { return pRetry(async () => { try { return await editor.editText(options); } catch (error) { if (error.code === 'RATE_LIMITED') { const retryAfter = error.retryAfter || 60; console.log(`Rate limited, retry dans ${retryAfter}s`); await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); throw error; // Déclenche un retry } throw new pRetry.AbortError(error); // Pas de retry pour autres erreurs } }, { retries: 3, factor: 2 }); }
-
Limitez la concurrence :
import pLimit from 'p-limit'; const limit = pLimit(2); // Max 2 requêtes simultanées const promesses = images.map(image => limit(() => editor.editText({ image, prompt: 'Modifier' })) ); const resultats = await Promise.allSettled(promesses);
🖼️ Problèmes d'Images
Image Trop Volumineuse
Erreur : IMAGE_TOO_LARGE
Error: Image size exceeds maximum limit of 10MB
Code: IMAGE_TOO_LARGE
Status: 413
Solutions :
-
Compressez l'image avant envoi :
import sharp from 'sharp'; async function compresserImage(cheminImage) { const buffer = await sharp(cheminImage) .resize(2048, 2048, { fit: 'inside', withoutEnlargement: true }) .jpeg({ quality: 85 }) .toBuffer(); return buffer; } const imageCompressee = await compresserImage('./grande-image.jpg'); const resultat = await editor.editText({ image: imageCompressee, prompt: 'Modifier le texte' });
-
Vérifiez la taille avant traitement :
import fs from 'fs'; function verifierTailleImage(cheminImage) { const stats = fs.statSync(cheminImage); const tailleMB = stats.size / (1024 * 1024); if (tailleMB > 10) { throw new Error(`Image trop volumineuse: ${tailleMB.toFixed(2)}MB (max: 10MB)`); } return tailleMB; } try { const taille = verifierTailleImage('./image.jpg'); console.log(`Taille de l'image: ${taille.toFixed(2)}MB`); } catch (error) { console.error(error.message); }
Format Non Supporté
Erreur : UNSUPPORTED_FORMAT
Error: Image format 'bmp' is not supported
Code: UNSUPPORTED_FORMAT
Status: 400
Solutions :
-
Convertissez au bon format :
import sharp from 'sharp'; async function convertirFormat(cheminImage, formatSortie = 'jpeg') { const buffer = await sharp(cheminImage) .toFormat(formatSortie) .toBuffer(); return buffer; } // Convertir BMP en JPEG const imageConvertie = await convertirFormat('./image.bmp', 'jpeg'); const resultat = await editor.editText({ image: imageConvertie, prompt: 'Modifier' });
-
Vérifiez le format avant traitement :
import path from 'path'; const formatsSupports = ['.jpg', '.jpeg', '.png', '.webp']; function verifierFormat(cheminImage) { const extension = path.extname(cheminImage).toLowerCase(); if (!formatsSupports.includes(extension)) { throw new Error(`Format non supporté: ${extension}. Utilisez: ${formatsSupports.join(', ')}`); } return extension; }
🌐 Problèmes Réseau
Timeout de Connexion
Erreur : CONNECTION_TIMEOUT
Error: Request timeout after 30000ms
Code: CONNECTION_TIMEOUT
Status: 408
Solutions :
-
Augmentez le timeout :
const editor = new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY, timeout: 60000 // 60 secondes au lieu de 30 });
-
Implémentez un retry avec timeout progressif :
async function editTextAvecTimeoutProgressif(options, tentative = 1) { const timeouts = [30000, 45000, 60000]; // Timeouts progressifs const timeout = timeouts[tentative - 1] || 60000; try { const editorAvecTimeout = new QwenImageEdit({ ...editor.config, timeout }); return await editorAvecTimeout.editText(options); } catch (error) { if (error.code === 'CONNECTION_TIMEOUT' && tentative < 3) { console.log(`Timeout tentative ${tentative}, retry avec timeout ${timeouts[tentative]}ms`); return editTextAvecTimeoutProgressif(options, tentative + 1); } throw error; } }
Erreur Réseau
Erreur : NETWORK_ERROR
Error: Network error: ENOTFOUND api.qwen.ai
Code: NETWORK_ERROR
Status: 0
Solutions :
-
Vérifiez la connectivité :
import { ping } from 'ping'; async function verifierConnectivite() { try { const resultat = await ping.promise.probe('api.qwen.ai'); if (!resultat.alive) { throw new Error('Impossible de joindre api.qwen.ai'); } console.log('✅ Connectivité OK'); } catch (error) { console.error('❌ Problème de connectivité:', error.message); } }
-
Configurez un proxy si nécessaire :
const editor = new QwenImageEdit({ apiKey: process.env.QWEN_API_KEY, proxy: { host: 'proxy.entreprise.com', port: 8080, auth: { username: process.env.PROXY_USER, password: process.env.PROXY_PASS } } });
⚙️ Erreurs de Traitement
Échec du Traitement
Erreur : PROCESSING_FAILED
Error: Failed to process image: Unable to detect text in image
Code: PROCESSING_FAILED
Status: 422
Solutions :
-
Améliorez la qualité de l'image :
import sharp from 'sharp'; async function ameliorerPourOCR(cheminImage) { return await sharp(cheminImage) .resize(2048, null, { withoutEnlargement: true }) .sharpen() .normalize() .toBuffer(); } const imageAmelioree = await ameliorerPourOCR('./image-floue.jpg'); const resultat = await editor.editText({ image: imageAmelioree, prompt: 'Modifier le texte' });
-
Analysez l'image d'abord :
// Vérifiez si l'image contient du texte détectable const analyse = await editor.analyzeImage({ image: './image.jpg', options: { detectText: true, confidence: 0.5 } }); if (!analyse.text || analyse.text.length === 0) { console.warn('Aucun texte détecté dans l\'image'); } else { console.log('Texte détecté:', analyse.text.map(t => t.content)); // Procéder avec l'édition }
Contenu Non Détecté
Erreur : CONTENT_NOT_DETECTED
Error: No editable content found matching the prompt
Code: CONTENT_NOT_DETECTED
Status: 422
Solutions :
-
Améliorez votre prompt :
// ❌ Prompt vague const mauvais = await editor.editText({ image: './affiche.jpg', prompt: 'Changer le texte' }); // ✅ Prompt spécifique const bon = await editor.editText({ image: './affiche.jpg', prompt: 'Remplacer le mot "Concert" par "Festival" dans le titre principal' });
-
Utilisez l'analyse pour guider vos prompts :
const analyse = await editor.analyzeImage({ image: './image.jpg', options: { detectText: true } }); console.log('Texte disponible:'); analyse.text.forEach((texte, index) => { console.log(`${index + 1}. "${texte.content}" (confiance: ${texte.confidence})`); }); // Utilisez le texte détecté dans votre prompt const resultat = await editor.editText({ image: './image.jpg', prompt: `Remplacer "${analyse.text[0].content}" par "Nouveau texte"` });
🐌 Problèmes de Performance
Traitement Lent
Symptôme : Les requêtes prennent plus de 30 secondes
Solutions :
-
Optimisez la taille des images :
async function optimiserPourVitesse(cheminImage) { return await sharp(cheminImage) .resize(1024, 1024, { fit: 'inside', withoutEnlargement: true }) .jpeg({ quality: 80 }) .toBuffer(); }
-
Utilisez le traitement asynchrone pour les gros volumes :
// Pour les traitements longs const job = await editor.editTextAsync({ image: './grande-image.jpg', prompt: 'Traitement complexe', callbackUrl: 'https://monsite.com/callback' }); console.log('Job démarré:', job.id); // Vérifier le statut périodiquement const interval = setInterval(async () => { const statut = await editor.getJobStatus(job.id); console.log('Progression:', statut.progress + '%'); if (statut.status === 'completed') { clearInterval(interval); console.log('Résultat:', statut.result); } }, 5000);
Mémoire Insuffisante
Erreur : INSUFFICIENT_MEMORY
Error: Insufficient memory to process image
Code: INSUFFICIENT_MEMORY
Status: 507
Solutions :
-
Traitez les images par lots plus petits :
import pLimit from 'p-limit'; const limit = pLimit(1); // Une seule image à la fois async function traiterParLots(images, tailleLot = 5) { const resultats = []; for (let i = 0; i < images.length; i += tailleLot) { const lot = images.slice(i, i + tailleLot); console.log(`Traitement du lot ${Math.floor(i/tailleLot) + 1}/${Math.ceil(images.length/tailleLot)}`); const resultatsLot = await Promise.allSettled( lot.map(image => limit(() => editor.editText({ image, prompt: 'Modifier' }))) ); resultats.push(...resultatsLot); // Pause entre les lots pour libérer la mémoire await new Promise(resolve => setTimeout(resolve, 1000)); } return resultats; }
-
Libérez la mémoire explicitement :
async function traiterAvecNettoyage(images) { for (const image of images) { try { const resultat = await editor.editText({ image, prompt: 'Modifier' }); console.log('Traité:', resultat.imageUrl); } catch (error) { console.error('Erreur:', error.message); } // Forcer le garbage collection si disponible if (global.gc) { global.gc(); } } }
🔧 Outils de Débogage
Logging Détaillé
const editor = new QwenImageEdit({
apiKey: process.env.QWEN_API_KEY,
logging: {
level: 'debug',
destination: 'console',
logRequests: true,
logResponses: true,
logErrors: true
}
});
// Activer le logging pour une requête spécifique
editor.on('request', (data) => {
console.log('📤 Requête:', {
method: data.method,
url: data.url,
headers: data.headers,
body: data.body ? 'Présent' : 'Absent'
});
});
editor.on('response', (data) => {
console.log('📥 Réponse:', {
status: data.status,
headers: data.headers,
duration: data.duration + 'ms'
});
});
Intercepteur de Requêtes
class IntercepteurDebug {
constructor(editor) {
this.editor = editor;
this.requetes = [];
}
async intercepter(methode, options) {
const debut = Date.now();
const id = Math.random().toString(36).substr(2, 9);
console.log(`🚀 [${id}] Début ${methode}:`, {
image: typeof options.image,
prompt: options.prompt?.substring(0, 50) + '...',
options: Object.keys(options.options || {})
});
try {
const resultat = await this.editor[methode](options);
const duree = Date.now() - debut;
console.log(`✅ [${id}] Succès ${methode} (${duree}ms):`, {
imageUrl: resultat.imageUrl,
credits: resultat.credits,
processingTime: resultat.processingTime
});
this.requetes.push({
id,
methode,
duree,
succes: true,
credits: resultat.credits
});
return resultat;
} catch (error) {
const duree = Date.now() - debut;
console.error(`❌ [${id}] Erreur ${methode} (${duree}ms):`, {
code: error.code,
message: error.message,
status: error.statusCode
});
this.requetes.push({
id,
methode,
duree,
succes: false,
erreur: error.code
});
throw error;
}
}
obtenirStatistiques() {
const total = this.requetes.length;
const succes = this.requetes.filter(r => r.succes).length;
const echecs = total - succes;
const dureemoyenne = this.requetes.reduce((acc, r) => acc + r.duree, 0) / total;
const creditsTotal = this.requetes.reduce((acc, r) => acc + (r.credits || 0), 0);
return {
total,
succes,
echecs,
tauxSucces: ((succes / total) * 100).toFixed(2) + '%',
dureemoyenne: Math.round(dureemoyenne) + 'ms',
creditsTotal
};
}
}
// Utilisation
const intercepteur = new IntercepteurDebug(editor);
// Wrapper pour les méthodes
const editorDebug = {
editText: (options) => intercepteur.intercepter('editText', options),
editElement: (options) => intercepteur.intercepter('editElement', options),
analyzeImage: (options) => intercepteur.intercepter('analyzeImage', options)
};
// Utiliser l'editor avec debug
const resultat = await editorDebug.editText({
image: './test.jpg',
prompt: 'Test'
});
console.log('Statistiques:', intercepteur.obtenirStatistiques());
Health Check
async function verifierSanteService() {
const tests = [
{
nom: 'Connectivité API',
test: async () => {
const quota = await editor.getQuotaInfo();
return quota.requestsRemaining > 0;
}
},
{
nom: 'Traitement simple',
test: async () => {
// Utiliser une petite image de test
const resultat = await editor.editText({
image: './test-small.jpg',
prompt: 'Test de santé'
});
return resultat.imageUrl !== null;
}
},
{
nom: 'Analyse d\'image',
test: async () => {
const analyse = await editor.analyzeImage({
image: './test-small.jpg'
});
return analyse.metadata !== null;
}
}
];
console.log('🏥 Vérification de santé du service...');
for (const test of tests) {
try {
const debut = Date.now();
const resultat = await test.test();
const duree = Date.now() - debut;
if (resultat) {
console.log(`✅ ${test.nom} (${duree}ms)`);
} else {
console.log(`⚠️ ${test.nom} - Test échoué (${duree}ms)`);
}
} catch (error) {
console.log(`❌ ${test.nom} - Erreur: ${error.message}`);
}
}
}
// Exécuter le health check
verifierSanteService();
📞 Support et Assistance
Si vous ne trouvez pas de solution à votre problème :
🌐 Ressources en Ligne
- Documentation : docs.qwen.ai
- FAQ : help.qwen.ai
- Status : status.qwen.ai
💬 Communauté
- Discord : discord.gg/qwen
- GitHub : github.com/qwen/image-edit
- Stack Overflow : Tag
qwen-image-edit
📧 Contact Direct
- Support technique : support@qwen.ai
- Bugs critiques : bugs@qwen.ai
- Demandes de fonctionnalités : features@qwen.ai
Informations à inclure dans votre demande :
- Version du SDK
- Code d'erreur exact
- Exemple de code reproduisant le problème
- Logs détaillés
- Environnement (Node.js version, OS, etc.)