HiAPI
Blog

Tutoriale

hiapi /v1/tasks attività bloccata o in timeout: flusso diagnostico e strategia di retry

Oct 13, 2026
hiapi /v1/tasks attività bloccata o in timeout: flusso diagnostico e strategia di retry

Hai inviato un'attività con POST https://api.hiapi.ai/v1/tasks, hai ottenuto un taskId, ma interrogando con GET /v1/tasks/{taskId} vedi che data.status resta fermo su queued o handling per diversi minuti — sembra "bloccata"; oppure il tuo ciclo di polling raggiunge il limite che hai impostato senza arrivare allo stato finale, e quindi segnala un timeout. Non affrettarti a reinviare: le attività di hiapi sono asincrone, "non ancora terminata" e "già fallita" sono due cose diverse; diagnostica con chiarezza prima di agire, così non peggiori la situazione.

Se vedi che data.status è già fail, che error.code è TASK_TIMEOUT, oppure se il browser/proxy restituisce un letterale HTTP 504 — quello è un altro tipo di problema (l'attività è davvero fallita, o il timeout si è verificato a livello di rete tra te e hiapi). Consulta Diagnosi dei timeout delle attività HiAPI e degli errori 504. Questo articolo tratta solo lo scenario "bloccato" in cui l'attività tarda a raggiungere lo stato finale.

Manifestazione del problema

Un'attività "bloccata", interrogata, appare più o meno così (HTTP 200, ma l'attività è ancora in uno stato non finale):

{
  "data": {
    "taskId": "…",
    "status": "queued",
    "output": null,
    "error": null
  }
}

Caratteristiche chiave: data.status è uno tra queued (in coda) / handling (in elaborazione) / archiving (in archiviazione), data.error è null, data.output non ha ancora contenuto. Questo indica che l'attività è sana, semplicemente non è ancora terminata.

Gli stati finali delle attività hiapi sono solo due: data.status uguale a success o fail. Finché non è uno di questi due, significa che l'attività non è conclusa — i "blocchi" si verificano quasi sempre in questa fase non finale.

Due "falsi blocchi" facilmente confondibili:

  • L'interrogazione restituisce direttamente 404:

    {"code": 404, "data": null, "message": "task not found"}
    

    Non è un blocco: il taskId è scritto male, l'attività non è stata creata con successo, oppure il record dell'attività è scaduto — verifica il data.taskId ottenuto al momento dell'invio.

  • Rifiuto sincrono già al momento dell'invio (non hai nemmeno ottenuto il taskId), ad esempio model scritto male:

    {"code": 400, "data": null, "error_code": "MODEL_UNAVAILABLE", "message": "model not available via /v1/tasks"}
    

    Questi sono problemi della richiesta stessa, non attività bloccate: correggi e reinvia.

Cause comuni (ordinate per probabilità)

1. Arretrato in coda (la più comune)

Quando un modello (modello immagine, modello video o qualsiasi modello ad alto carico di calcolo) viene chiamato intensamente, la tua attività attende nella coda di quel modello di essere presa in carico da un worker.

  • Segnale: data.status è queued, data.error è null, e non è passato molto tempo dall'invio.
  • Rimedio: rallenta il ritmo di polling, 5–10 secondi per interrogazione bastano; non girare a vuoto ogni 100ms. La maggior parte delle attività viene presa in carico entro uno o due minuti.

2. I modelli pesanti richiedono tempo

L'attività è già stata presa in carico (handling/archiving), ma questo modello impiega fisiologicamente molto tempo per completare un'esecuzione — video lunghi, alta risoluzione, molte immagini di riferimento allungano notevolmente i tempi.

  • Segnale: data.status è handling o archiving, persiste per diversi minuti ma senza errori.
  • Rimedio: concedi alle attività pesanti un limite di polling più ampio (lascia margine in base alle capacità del modello). Tempo lungo ≠ fallimento; non interromperla proprio quando sta per produrre il risultato.

3. Modalità di polling sbagliata (la più facilmente scambiata per "blocco")

Molti "blocchi" sono in realtà problemi del client: intervallo di polling troppo breve che confonde, nessun limite impostato, oppure limite troppo breve e abbandono prematuro.

  • Segnale: il data.status del server avanza normalmente, ma il tuo ciclo lancia un timeout in anticipo, oppure non stai proprio leggendo data.status.
  • Rimedio: usa un intervallo fisso (consigliato 5 secondi) + un limite ragionevole (circa 10 minuti per attività normali, di più per quelle pesanti). Il timeout deve essere determinato dal tuo ciclo, non aspettandoti uno stato timeout dal server — hiapi non ha questo stato.

4. Endpoint di callback irraggiungibile

Se all'invio dell'attività hai incluso un callback, l'attività stessa potrebbe essere già success, ma il risultato non riesce ad arrivare a te, quindi sembra "ferma".

  • Segnale: interrogando attivamente data.status è già success, data.output ha contenuto, ma il tuo endpoint di callback non ha ricevuto nulla.
  • Rimedio: l'indirizzo di callback deve essere raggiungibile da Internet, accettare POST e restituire 2xx entro circa 10 secondi; altrimenti passa al polling. Dettagli in Perché il callback delle attività hiapi non si attiva.

Passi di risoluzione

  1. Interroga prima lo stato, non reinviare a sensazione: GET /v1/tasks/{taskId}, leggi data.status e data.error.
  2. Smista in base allo stato:
    • queued / handling / archiving → è ancora in esecuzione, attendi 5–10 secondi e interroga di nuovo (cause 1 / 2).
    • success → attività riuscita, prendi il risultato da data.output; se aspettavi un callback e non è arrivato → causa 4.
    • fail → leggi data.error.code e data.error.message; se è TASK_TIMEOUT → vedi guida timeout e 504.
    • 404 task not found → taskId errato o non creato con successo; ricontrolla data.taskId nella risposta di invio.
  3. output ha una scadenza: gli URL di download in data.output hanno expireAt (circa 7 giorni); una volta ottenuti, salvali su disco / trasferiscili al più presto, non conservare hotlink a lungo.
  4. Verifica che non sia un problema di autenticazione / richiesta: esegui prima l'esempio di verifica minimale qui sotto, per escludere problemi con key e model id.
  5. Se devi davvero ritentare, usa il backoff: vedi la sezione successiva sulla strategia di retry; non reinviare ripetutamente lo stesso body in un ciclo serrato.

Esempio di verifica minimale

Usa una richiesta minimale per confermare che key e interfaccia attività funzionino. Usa il model con id nudo (es.: gpt-image-2):

curl -s -X POST https://api.hiapi.ai/v1/tasks \
  -H "Authorization: Bearer $HIAPI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "input": { "prompt": "a single red apple on a white background, studio lighting" }
  }'

Un invio riuscito restituisce una risposta simile a {"data":{"taskId":"…","status":"queued"}}. Prendi il taskId e interroga:

curl -s "https://api.hiapi.ai/v1/tasks/<taskId>" \
  -H "Authorization: Bearer $HIAPI_API_KEY"

Strategia di retry che non peggiora le cose

  1. Backoff esponenziale: consigliato 5s → 15s → 45s.
  2. Massimo 3 tentativi: se fallisce anche il terzo, passa all'escalation (cambia modello, riduci la configurazione o apri un ticket); niente cicli infiniti.
  3. Ogni retry è una nuova attività: un POST /v1/tasks è un nuovo taskId e può generare nuova fatturazione. hiapi non offre un "reinvia idempotente" garantito — non aspettarti che reinviare lo stesso body riutilizzi la vecchia attività.
  4. Quando incontri un 429, rallenta la velocità di invio, non quella di polling: vedi Come risolvere l'errore di rate limit (429) di hiapi.

Un esempio Python affidabile di polling + backoff:

import time, os, requests

BASE = "https://api.hiapi.ai/v1/tasks"
HEADERS = {"Authorization": f"Bearer {os.environ['HIAPI_API_KEY']}"}

def submit_and_wait(body, poll_interval=5, max_wait=600):
    r = requests.post(BASE, json=body, headers=HEADERS, timeout=30)
    r.raise_for_status()
    task_id = r.json()["data"]["taskId"]

    deadline = time.time() + max_wait
    while time.time() < deadline:
        time.sleep(poll_interval)
        data = requests.get(f"{BASE}/{task_id}", headers=HEADERS, timeout=30).json()
        status = (data.get("data") or {}).get("status")
        if status == "success":
            return data["data"]["output"]
        if status == "fail":
            raise RuntimeError(data["data"].get("error"))
        # queued / handling / archiving → continua ad attendere
    raise TimeoutError(f"task {task_id} non ha raggiunto lo stato finale entro {max_wait}s")

Nota che la determinazione dello stato finale riconosce solo success e fail; tutti gli altri stati (queued / handling / archiving) continuano ad attendere, e il timeout è deciso dal tuo max_wait.

Quando passare all'escalation

  • Con retry con backoff per 3 volte, ogni volta lo stesso data.error.code → non è un jitter transitorio, cambia input o modello.
  • L'attività resta a lungo in queued senza alcun progresso → vai alla console hiapi per vedere se ci sono notifiche della piattaforma, e apri un ticket con il request_id.
  • data.status è già success ma il callback non arriva mai → smetti di affidarti al callback per quell'endpoint e passa al polling.

Link interni correlati

FAQ

D: Quanto tempo equivale a "timeout"? Esiste una durata di timeout uniforme? R: Non c'è un numero uniforme, dipende dal modello; le attività pesanti (video lunghi, alta risoluzione) richiedono più tempo. Inoltre hiapi non ha uno stato timeout lato server — il cosiddetto timeout è di solito il tuo ciclo di polling che raggiunge il limite che hai impostato. Un'attività che va davvero in timeout lato server sarà data.status:"fail" + error.code:"TASK_TIMEOUT"; in quel caso vedi guida timeout e 504.

D: L'attività è in queued da 30 secondi, conviene annullare e riprovare? R: No. 30 secondi rientrano nella norma per qualsiasi modello non banale; attendi almeno due minuti prima di considerare un retry.

D: Si può annullare un'attività in esecuzione? R: In genere l'annullamento non è supportato; anche se fosse possibile, la coda / lo slot di calcolo sono di solito già occupati. Conviene lasciarla completare e interrogare il risultato.

D: La stessa richiesta funzionava ieri, oggi è bloccata? R: Nella stragrande maggioranza dei casi è arretrato in coda a livello di modello (causa 1). Passa a un modello con capacità simili, oppure attendi 5–10 minuti che la coda si riduca e riprova.

D: Ogni attività va in timeout, è un problema del mio account? R: Vai prima alla console hiapi per vedere se ci sono notifiche a livello di account, poi verifica se sei soggetto a rate limit (vedi guida 429). Se è tutto normale e solo un certo modello fallisce, allora è probabilmente la coda o il backend di quel modello, non il tuo account.

D: Ritentare un'attività bloccata / in timeout comporta una doppia fatturazione? R: Ogni POST /v1/tasks è una nuova attività fatturata. Le attività fallite che non producono risultati di solito non addebitano il costo di produzione, ma la coda / lo slot di calcolo potrebbero essere già occupati. Se ti interessa il costo, verifica a posteriori nella pagina di utilizzo.

Inizia a creare con artefatti IA persistenti

Ottieni la tua chiave API e chiama modelli di immagini, video e audio tramite un'unica API basata sui task.

Leggi la documentazione API