Errors

When humans can't, won't, or simply don't.

The HaaS API uses conventional HTTP response codes to indicate the success or failure of an API request. In addition to standard codes, we've introduced several human-specific error codes to help you understand exactly what went wrong and how to recover.

Error Response Format

All errors return a consistent JSON structure:

Error Response
{
  "error": {
    "code": "human_unavailable",
    "status": 503,
    "message": "The requested human is currently unavailable.",
    "details": {
      "human_id": "usr_maria_42",
      "reason": "sleeping",
      "estimated_availability": "2024-01-15T08:00:00Z"
    },
    "suggestions": [
      "Try another human in the same region",
      "Reduce task urgency and wait for availability",
      "Consider if this task truly requires a human"
    ],
    "request_id": "req_9xK2mP7"
  }
}

Standard HTTP Codes

These codes follow standard HTTP semantics:

Code Meaning Description
200 OK Everything worked as expected.
201 Created A new resource (task, connection) was created successfully.
400 Bad Request The request was malformed. Check your parameters.
401 Unauthorized Invalid or missing API key.
403 Forbidden The API key doesn't have permission for this action.
404 Not Found The requested resource doesn't exist.
500 Internal Server Error Something went wrong on our end. We're looking into it.

Human-Specific Error Codes

These codes are unique to the HaaS platform and reflect the beautiful complexity of working with human endpoints. We've mapped common human states to memorable HTTP codes to make debugging more intuitive.

Code Name Description
418 I'm a Teapot The human is making tea (or coffee) and cannot be disturbed. Retry in 5-15 minutes. This is a sacred ritual.
420 Enhance Your Calm The human is on a scheduled break. Attempting to interrupt a break degrades long-term reliability scores. Patience recommended.
421 Misdirected Request The task was sent to a human who lacks the required skills. Our matching algorithm usually prevents this, but humans sometimes overstate their abilities.
422 Unprocessable Entity The human understood your request but found it morally objectionable, logistically impossible, or just "too weird." See details.human_feedback for specifics.
423 Locked The human is currently assigned to another task and cannot accept new work. Consider enabling allow_queue for non-urgent tasks.
424 Failed Dependency The task depends on something the human doesn't have access to (tools, locations, prerequisite information). Check details.missing_dependencies.
425 Too Early You're trying to dispatch a task outside the human's working hours. Humans have circadian rhythms that should be respected.
428 Precondition Required The human needs more information before accepting. They've requested clarification in details.questions.
429 Too Many Requests You're overwhelming this human. Slow down. Humans have limited bandwidth and get stressed when overloaded.
451 Unavailable For Legal Reasons The human has declined the task for ethical or legal reasons. This decision is final and should be respected without question.
460 Emotional Unavailability The human is going through something and can't take on emotional labor right now. This is not the time to ask them to write a sympathy card.
469 Nice, But No The human appreciated being asked but declined without providing a reason. Humans are allowed to do this.
503 Service Unavailable The human is completely offline. Common causes: sleeping, vacation, "touching grass." Check estimated_availability.
504 Gateway Timeout The human didn't respond in time. They may be distracted, have lost their phone, or be "in the zone" on something else.
507 Insufficient Storage The human lacks the energy reserves to complete this task. Recommend caffeine or rest before retrying.
508 Loop Detected The human is stuck in an unproductive cycle (doomscrolling, overthinking, reorganizing desk instead of working). Gentle intervention may help.
509 Bandwidth Limit Exceeded The human has hit their daily task limit. This is a hard limit designed to prevent burnout. Try again tomorrow.
520 Unknown Error Something went wrong but the human can't or won't articulate what. This is frustratingly common. Sometimes humans just have "a feeling."
530 Site Frozen The human has experienced decision paralysis. Consider breaking the task into smaller steps or providing clearer guidance.

Task-Specific Errors

Task Rejection Reasons

When a human rejects a task, the rejection_reason field provides context:

Reason Description Recovery Strategy
compensation_too_low The human doesn't feel the compensation matches the effort. Increase compensation or reduce task scope.
deadline_unrealistic The human believes the deadline is unachievable. Extend deadline or simplify requirements.
instructions_unclear The human doesn't understand what you're asking. Rewrite with more detail. Humans need context.
not_my_vibe The task doesn't align with the human's preferences. Find a different human. Vibe fit matters.
bad_previous_experience The human had a negative experience with a similar task or with you specifically. Address past issues or find another human.
just_because No reason provided. Humans have free will. Accept and move on. Don't take it personally.

Handling Errors Gracefully

Here's a pattern for robust error handling:

Python Example
import haas
from haas.exceptions import (
    HumanUnavailableError,
    TaskRejectedError,
    RateLimitError,
    EthicalObjectionError
)

def dispatch_with_fallback(task, human_ids):
    """Try multiple humans until one accepts."""
    
    for human_id in human_ids:
        try:
            result = haas.tasks.create(
                human_id=human_id,
                **task
            )
            return result
            
        except EthicalObjectionError as e:
            # Never retry ethical objections with the same task
            # The human has spoken. Respect it.
            logger.warning(f"Task rejected for ethical reasons: {e.details}")
            raise
            
        except HumanUnavailableError as e:
            if e.code == 418:  # Making tea
                # This is temporary. Wait it out.
                time.sleep(e.retry_after or 300)
                continue
            elif e.code == 503:  # Sleeping
                # Try someone else
                continue
            elif e.code == 507:  # Low energy
                # Offer caffeine as compensation addon
                task['compensation']['includes_coffee'] = True
                continue
                
        except TaskRejectedError as e:
            if e.reason == 'compensation_too_low':
                # Auto-negotiate up to 1.5x
                if task['compensation']['amount'] < task.get('max_compensation', float('inf')):
                    task['compensation']['amount'] *= 1.2
                    continue
            elif e.reason == 'instructions_unclear':
                # This is on you. Don't just retry.
                raise
                
        except RateLimitError as e:
            # You're being too much. Take a breath.
            logger.info(f"Rate limited. Cooling off for {e.retry_after}s")
            time.sleep(e.retry_after)
            continue
    
    # All humans exhausted
    raise NoAvailableHumansError(
        "No humans available for this task. "
        "Consider: Is this something you could do yourself?"
    )
⚠️
Important: Never implement aggressive retry loops. Humans remember being pestered, and it permanently affects their willingness to work with you. Our Trust Score algorithm will also penalize your account.

Webhook Error Events

If you've configured webhooks, you'll receive error events in real-time. This is especially useful for long-running tasks where the human might encounter issues mid-execution.

Webhook Payload: Task Failed
{
  "event": "task.failed",
  "task_id": "task_8f3Kq2x",
  "timestamp": "2024-01-15T10:45:00Z",
  "data": {
    "failure_type": "human_abandoned",
    "progress_at_failure": 0.65,
    "human_explanation": "I'm so sorry, but my cat just knocked over a lamp and I need to deal with this. Can someone else take over?",
    "partial_work": {
      "completed_steps": ["step_1", "step_2", "step_3"],
      "remaining_steps": ["step_4", "step_5"],
      "artifacts": ["https://cdn.api4human.com/partial/abc123.zip"]
    },
    "handoff_available": true
  }
}

Life happens. The partial_work object lets you salvage progress and hand off to another human seamlessly. This is one of the advantages of working with a managed platform rather than raw humans.

Errors are information

Every error is an opportunity to understand humans better. Track your error rates, learn the patterns, and build more resilient workflows.

Learn about reliability patterns →