> ## Documentation Index
> Fetch the complete documentation index at: https://tbd-6fc993ce-hypeship-invocation-failure-reasons.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Status

Once you've [deployed](/apps/deploy) an app and invoked it, you can monitor its status using streaming for real-time updates or polling for periodic checks.

<Info>
  An invocation ends once its code execution finishes.
</Info>

## Streaming Status Updates

For real-time status monitoring, use `follow` to [stream invocation events](https://kernel.sh/docs/api-reference/invocations/stream-invocation-events-via-sse). This provides immediate updates as your invocation progresses and is more efficient than polling.

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  import Kernel from '@onkernel/sdk';

  const kernel = new Kernel();

  const response = await kernel.invocations.follow('id');
  console.log(response);
  ```

  ```python Python theme={null}
  from kernel import Kernel

  kernel = Kernel()

  response = kernel.invocations.follow(id="id")
  print(response)
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/kernel/kernel-go-sdk"
  )

  func main() {
  	ctx := context.Background()
  	client := kernel.NewClient()

  	stream := client.Invocations.FollowStreaming(ctx, "id", kernel.InvocationFollowParams{})
  	defer stream.Close()

  	for stream.Next() {
  		event := stream.Current()
  		if event.Event == "invocation_state" {
  			fmt.Println(event.Invocation.Status)
  		}
  	}
  	if err := stream.Err(); err != nil {
  		panic(err)
  	}
  }
  ```
</CodeGroup>

### Example

Here's an example showing how to handle streaming status updates:

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  const result = await kernel.invocations.retrieve(invocation.id);
  const follow = await kernel.invocations.follow(result.id);

  for await (const evt of follow) {
    if (evt.event === 'invocation_state') {
      console.log(`Status: ${evt.invocation.status}`);

      if (evt.invocation.status === 'succeeded') {
        console.log('Invocation completed successfully');
        if (evt.invocation.output) {
          console.log('Result:', JSON.parse(evt.invocation.output));
        }
        break;
      } else if (evt.invocation.status === 'failed') {
        console.error(evt.invocation.status_reason ?? 'Invocation failed.');
        break;
      }
    } else if (evt.event === 'error') {
      console.error('Error:', evt.error.message);
      break;
    }
  }
  ```

  ```python Python theme={null}
  import json

  from kernel import Kernel

  kernel = Kernel()

  for evt in kernel.invocations.follow("rr33xuugxj9h0bkf1rdt2bet"):
      if evt.event == "invocation_state":
          invocation = evt.invocation
          print(f"Status: {invocation.status}")
          if invocation.status == "succeeded":
              if invocation.output:
                  print("Result:", json.loads(invocation.output))
              break
          if invocation.status == "failed":
              print(invocation.status_reason or "Invocation failed.")
              break
      elif evt.event == "error":
          print("Error:", evt.error.message)
          break
  ```
</CodeGroup>

## Failure details

A failed invocation has two distinct fields:

* `status_reason`: A nonempty, customer-safe failure summary. It's present when `status` is `failed` and omitted for other statuses. Recognized messages, such as timeout or startup failure messages, receive specific summaries. Unrecognized failures receive `"Invocation failed. See output for details."`; failures with no recorded reason receive `"Invocation failed; no failure reason was recorded."`.
* `output`: The original action result or detailed failure output. It's optional and often JSON-encoded, but failures can contain plain text. Don't assume that every failure output can be parsed as JSON.

These rules apply to streaming events, retrieval, listing, and synchronous invocation responses. The first failed `invocation_state` event includes `status_reason`. Historical invocations also receive a summary when you retrieve or stream them; no rerun is needed. During rollout, if `status_reason` is absent, inspect `output` for the recorded error.

For example, a timeout returns these fields alongside the invocation's ID and other metadata:

```json theme={null}
{
  "status": "failed",
  "status_reason": "Invocation timed out after 900 seconds.",
  "output": "{\"error\":\"timed out after 900 seconds\"}"
}
```

Use `status_reason` to display the failure and inspect `output` separately for diagnostics. Summaries match the recorded error text, which can come from either the platform or your action code. A matching message doesn't establish where the failure originated. Reason text can change; don't use it as a stable identifier for retry decisions.

<Warning>
  Detailed output can contain sensitive application data, including account details or credentials. Restrict access and redact it before sharing or logging it. Failure summaries don't copy arbitrary application errors or internal traces.
</Warning>

## Polling Status Updates

Alternatively, you can poll the status endpoint using `retrieve` to check the invocation status periodically.

<CodeGroup>
  ```typescript Typescript/Javascript theme={null}
  import Kernel from '@onkernel/sdk';

  const kernel = new Kernel();

  const invocation = await kernel.invocations.retrieve('rr33xuugxj9h0bkf1rdt2bet');
  console.log(invocation.status);
  ```

  ```python Python theme={null}
  from kernel import Kernel

  kernel = Kernel()

  invocation = kernel.invocations.retrieve("rr33xuugxj9h0bkf1rdt2bet")
  print(invocation.status)
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"fmt"

  	"github.com/kernel/kernel-go-sdk"
  )

  func main() {
  	ctx := context.Background()
  	client := kernel.NewClient()

  	invocation, err := client.Invocations.Get(ctx, "rr33xuugxj9h0bkf1rdt2bet")
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(invocation.Status)
  }
  ```
</CodeGroup>
