Tutoriale
Attività HiAPI che restituisce TASK_FAILED: cause e come risolverle
Interpreta la risposta finale di un'attività, correggi ogni tipo di causa e distingui i veri fallimenti da errori 4xx e timeout.
Quando invii un'attività asincrona all'endpoint delle attività di HiAPI, un invio riuscito restituisce HTTP 200 e un taskId. L'attività viene poi eseguita in background e, quando la interroghi, potrebbe terminare in stato finale fail. In quel caso la risposta al polling sarà più o meno così — nota che la chiamata HTTP in sé resta 200:
{
"code": 200,
"data": {
"taskId": "tk-hiapi-01M4RK...",
"model": "seedream-5.0-lite/image-to-image",
"status": "fail",
"error": { "code": "TASK_FAILED", "message": "task failed" },
"created": 1791827316,
"completed": 1791827352,
"storage": "temp"
},
"message": "success"
}
È quello che tutti chiamano «errore TASK_FAILED»: la richiesta è stata accettata, l'attività è stata eseguita e alla fine non è riuscita. Non è un errore HTTP 4xx e non è nemmeno un timeout. Questo articolo ti insegna a interpretare questa risposta e a correggere uno per uno i vari tipi di causa.
Prima di tutto: TASK_FAILED non è un codice di stato HTTP
Il punto più importante da capire:
- Il codice di stato HTTP della chiamata di polling è
200e nel corpo della risposta c'è perfino"message": "success"— questo indica solo che la chiamata API è riuscita, non che la tua attività sia riuscita. - È
"status": "fail"(dentrodata) il criterio per stabilire che l'attività è fallita. Per un'attività completata,data.statuspuò essere solo"success"o"fail". TASK_FAILEDè il valore didata.error.code, non di status. Alcuni fallimenti portano un code più specifico e un message più utile (vedi sotto).
Quindi interroga sempre GET /v1/tasks/{taskId} e usa data.status come base per il branching: non giudicare mai l'esito guardando solo il codice di stato HTTP.
Individuare la causa dal dettaglio dell'attività
Una volta ottenuta la risposta finale, leggi i campi di data in questo ordine:
- Guarda prima
data.status— l'attività è fallita solo se è"fail". - Leggi poi
data.error.code— è la categoria di errore interpretabile dalla macchina (ad esempioTASK_FAILED,INVALID_REQUEST,CONTENT_POLICY_VIOLATION). - Leggi infine
data.error.message— è la spiegazione per un essere umano, che di solito indica direttamente la causa (per esempio un certo URL di input che non si riesce a scaricare).
error.code determina in pratica se questo fallimento «si può risolvere con un retry»: il generico TASK_FAILED (con message spesso "task failed") è di solito un problema transitorio e si può ritentare; quelli con un code esplicito (come INVALID_REQUEST, CONTENT_POLICY_VIOLATION) sono fallimenti deterministici: per quante volte ritenti senza cambiare l'input, il risultato sarà lo stesso.
Cause comuni di stato finale fail
Più o meno in ordine di frequenza decrescente.
1. URL di immagine / video di input non accessibile o non pubblico
È la causa più comune per le attività image-to-image e image/video-to-video. Se il tuo input fa riferimento a un URL che la piattaforma non riesce a scaricare, l'attività viene accettata ma fallisce durante l'esecuzione. Una risposta finale reale:
"error": {
"code": "INVALID_REQUEST",
"message": "The image URL could not be downloaded. Please provide a reachable public HTTP(S) URL and try again."
}
Qui il message è già molto chiaro. Altri modelli espongono la stessa causa radice come generico TASK_FAILED / "task failed".
Correzione: ospita l'input su un URL HTTPS accessibile pubblicamente e verificalo prima di inviare:
curl -I "https://your-host.example.com/input.png"
# deve restituire 200 e un content-type di media diretto (image/* o video/*)
# non deve essere 401/403/404, né una pagina HTML
URL pre-signed scaduti, indirizzi localhost / di rete interna e link che richiedono il login sono le trappole più comuni. Questi sono fallimenti deterministici: finché non sistemi l'URL, ritentare farà solo rieseguire inutilmente l'attività.
2. Fallimento transitorio o di generazione a monte
A volte un'attività dal formato del tutto corretto fallisce con il generico error.code: "TASK_FAILED", message: "task failed" e senza altri dettagli. Nella maggior parte dei casi si tratta di un glitch transitorio.
Correzione: ritenta una o due volte. Se fallisce ripetutamente con lo stesso input, semplifica l'input (accorcia il prompt, rimuovi i campi opzionali) e riprova, per restringere l'ambito della causa.
3. Contenuto bloccato dalle policy di sicurezza
Se il prompt o l'immagine di input violano le policy di sicurezza dei contenuti della piattaforma, l'attività termina con un errore deterministico di tipo policy, con data.error.code uguale a CONTENT_POLICY_VIOLATION.
Correzione: è un fallimento permanente, ritentare non serve. Modifica il prompt e i materiali di input, rimuovi i contenuti non conformi e invia di nuovo.
4. Un parametro che il modello rifiuta solo a runtime
La stragrande maggioranza dei parametri non validi viene bloccata già all'invio con HTTP 400 (non ottieni nemmeno il taskId) — vedi la sezione successiva. Ogni tanto un'opzione di per sé valida, ma non supportata dal modello in combinazione con altre, viene rifiutata solo durante l'esecuzione e finisce in data.status: "fail". error.message indica quale opzione è.
Correzione: leggi data.error.message, poi verifica sulla pagina del modello quali input supporta (ad esempio la pagina del modello GPT Image 2), ed elimina o correggi il campo che viene indicato.
Come distinguere TASK_FAILED, 4xx e timeout
Ci sono tre situazioni completamente diverse che vengono tutte chiamate genericamente «fallite», ma il modo di correggerle è diverso:
| Cosa vedi | Significato | Dove correggere |
|---|---|---|
Il POST restituisce non-2xx (400/401/402/429) e nessun taskId |
La richiesta è stata rifiutata, nessuna attività è mai partita | Correggi richiesta / key / saldo (vedi link sotto) |
Il POST restituisce 200 + taskId e il polling mostra data.status: "fail" |
TASK_FAILED — l'attività è stata eseguita ed è fallita | Leggi data.error.message (questo articolo) |
Il POST restituisce 200 + taskId e il polling, oltre la tua scadenza, resta in uno stato non finale (ad esempio handling) |
Timeout, non fallimento | Continua a fare polling / aumenta il timeout / ritenta |
Se non hai nemmeno ottenuto il taskId, allora non è un TASK_FAILED ma un errore di richiesta:
HTTP 400parametro non valido, mancante o non supportato → Correggere l'errore di parametro 400 di HiAPIHTTP 401API key non valida → Errore API Key non valida- Saldo insufficiente (rifiutato già alla creazione, quindi non c'è nessuna attività da far fallire) → Correggere il 402 saldo insufficiente di HiAPI
- Id modello sconosciuto o non ancora pubblicato (
MODEL_UNAVAILABLE) → «Modello inesistente / non disponibile» - L'attività non raggiunge mai uno stato finale → Timeout delle attività HiAPI ed errore 504
Il fallimento di autenticazione viene rifiutato già a livello di richiesta: la risposta è HTTP 401 + {"error":{"code":"permission_denied","type":"hiapi_error","request_id":"..."}}, non viene creata alcuna attività e quindi non si può nemmeno parlare di TASK_FAILED.
Checklist di correzione
- Interroga l'attività, non fidarti solo del POST. L'invio ti dice solo che l'attività è in coda. Chiama
GET /v1/tasks/{taskId}e guardadata.status. - Verifica che sia un vero fallimento:
data.status == "fail"(il codice HTTP resta200). - Leggi
data.error.codeedata.error.message. Il message è il tuo segnale principale. - Se si parla di URL di input: rendi l'URL raggiungibile pubblicamente e verificalo con
curl -I(200 + content-type di media diretto). - Se il message è generico (
"task failed"): trattalo come problema transitorio e ritenta; se fallisce ancora ripetutamente, semplifica l'input. - Se è un errore deterministico come
CONTENT_POLICY_VIOLATION: è un fallimento permanente, non ritentare automaticamente — serve modificare l'input. - Verifica che l'id modello sia presente in
GET /v1/modelse identico a quello che invii. Un id sconosciuto fallisce all'invio con400 MODEL_UNAVAILABLE, non con un fail finale. - Nessun
taskId? Allora non è un TASK_FAILED — passa alla guida corrispondente sugli errori di richiesta qui sopra.
Esempio minimo di verifica
Prima di diagnosticare una specifica attività, usa una richiesta pulita per confermare che la tua key e la connettività funzionino. Chiama l'endpoint unificato delle attività POST https://api.hiapi.ai/v1/tasks, usando l'id del modello in forma nuda (senza suffisso endpoint):
# 1) invio — atteso HTTP 200 + un taskId
curl -s https://api.hiapi.ai/v1/tasks \
-H "Authorization: Bearer sk-YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-image-2","input":{"prompt":"a red bicycle on a white background","aspect_ratio":"1:1"}}'
# -> {"code":200,"data":{"taskId":"tk-hiapi-..."},"message":"success"}
# 2) polling — inserisci il taskId che hai ottenuto
curl -s https://api.hiapi.ai/v1/tasks/tk-hiapi-xxxxxxxx \
-H "Authorization: Bearer sk-YOUR_KEY"
# -> durante l'esecuzione data.status è "handling", poi diventa "success" o "fail"
Se il passo 1 restituisce 200 e un taskId, la tua key e l'endpoint funzionano: qualsiasi fallimento è un problema della singola attività, non dell'integrazione. Se il passo 1 restituisce 401, la key non è corretta — gestisci la key dalla console HiAPI. Nota: questo esempio invia una generazione reale e comporta un costo.
Sul costo: non pagare ripetutamente per attività destinate a fallire
Per sapere se le attività fallite vengono addebitate e come funzionano la prenotazione e il rimborso, vedi Le richieste fallite di HiAPI vengono addebitate?. Due punti chiave:
- Non ritentare automaticamente alla cieca i fallimenti deterministici. Per
CONTENT_POLICY_VIOLATION, URL irraggiungibili e simili, ogni retry è una nuova attività e può essere addebitato. Cambia prima l'input, non far girare a vuoto la logica di retry bruciando soldi. - Verifica l'URL di input con
curl -Iprima di inviare. Un controllo HEAD è gratuito, mentre un'attività destinata a fallire per un link rotto potrebbe costare.
FAQ
TASK_FAILED è un codice di stato HTTP?
No. La chiamata HTTP restituisce 200. TASK_FAILED è il valore di data.error.code nella risposta finale, e in quella risposta data.status è "fail".
data.status è "fail", ma io cercavo "TASK_FAILED" — quale devo guardare?
Ognuno al proprio posto. Per un'attività completata, data.status è sempre "success" o "fail"; TASK_FAILED è un generico data.error.code, e un'attività fallita può anche portare un code più specifico (come INVALID_REQUEST, CONTENT_POLICY_VIOLATION) e un message su cui puoi agire.
Quali TASK_FAILED si possono ritentare e quali no?
Il generico "task failed" (senza altri dettagli) è per lo più un problema transitorio e si può ritentare una o due volte; i fallimenti deterministici con code esplicito (URL rotto → INVALID_REQUEST, contenuto non conforme → CONTENT_POLICY_VIOLATION, parametro rifiutato dal modello) non si risolvono ritentando: bisogna cambiare l'input.
La mia attività resta in handling, non fallisce né riesce.
È un timeout, non un fallimento. Continua a interrogare o aumenta il timeout del client; vedi Timeout delle attività HiAPI ed errore 504.
Ho ricevuto 400 / 401 / 402, non un taskId.
Quelli sono rifiuti della richiesta — non è stata creata alcuna attività, quindi non c'è nessun «fallimento». Usa le guide linkate sopra per correggere richiesta, key o saldo.
Le attività fallite vengono addebitate? Vedi Le richieste fallite di HiAPI vengono addebitate? per capire come vengono gestiti prenotazione e rimborso in caso di fallimento.
Come faccio a confermare che l'URL di input sia rotto?
Leggi data.error.message. I problemi di URL di solito indicano che l'immagine o il video non può essere scaricato; verifica con curl -I che il link restituisca 200 e sia un file media diretto.
Articoli correlati
Vedi tutti gli articoli →-
Tutoriale
Come chiamare hailuo-2.3-fast/image-to-video tramite l'API HiAPI: pratica con curl e Python
La prima richiesta funzionante per il livello image-to-video veloce ed economico — dall'ID del modello al download di un MP4
-
Tutoriale
Come chiamare hailuo-2.3/text-to-video tramite l'API HiAPI: curl, Python ed esempi di richiesta eseguibili
-
Tutoriale
Utilizzare Kandinsky 6.0 Pro su HiAPI per la generazione di video da testo: tutorial con curl e Python
Dimostrazione pratica guidata dalla richiesta: costruire la chiamata da prompt a clip video, inviare la richiesta, monitorare lo stato di completamento e scaricare il risultato