Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ This changelog is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.
- Added `examples/token_create_transaction_wipe_key.py` to demonstrate token wiping and the role of the wipe key.
- Added `examples/account_allowance_approve_transaction_hbar.py` and `examples/account_allowance_delete_transaction_hbar.py`, deleted `examples/account_allowance_hbar.py`. [#775]
- Added `docs\sdk_developers\training\receipts.md` as a training guide for users to understand hedera receipts.
- Add comprehensive documentation for `MaxAttemptsError` in `docs/sdk_developers/training/max_attempts_error.md` (2025-11-26)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello please move these changelog entries to the UNRELEASED section 👍
i.e. under added roughly in line 10

  • Add comprehensive documentation for MaxAttemptsError in docs/sdk_developers/training/max_attempts_error.md (2025-11-26)
  • Add practical example examples/errors/max_attempts_error.py demonstrating network error handling and recovery strategies (2025-11-26)
  • Document error handling patterns for network failures and node retry attempts (Create docs/sdk_developers/training/max_attempts_error.md #877)

- Add practical example `examples/errors/max_attempts_error.py` demonstrating network error handling and recovery strategies (2025-11-26)
- Document error handling patterns for network failures and node retry attempts (#877)
- Add `set_token_ids`, `_from_proto`, `_validate_checksum` to TokenAssociateTransaction [#795]
- docs: added `network_and_client.md` with a table of contents, and added external example scripts (`client.py`).

Expand Down
123 changes: 123 additions & 0 deletions docs/sdk_developers/training/max_attempts_error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
# MaxAttemptsError

## Overview

`MaxAttemptsError` is an exception that occurs when the SDK has exhausted all retry attempts to communicate with a Hedera network node. This error represents transient network issues or node unavailability rather than transaction logic errors.

## When It Occurs

`MaxAttemptsError` is raised when:
- A node repeatedly fails to respond to requests
- Network connectivity issues prevent communication with a node
- The node is temporarily unavailable or overloaded
- Multiple retry attempts have all failed

## Error Attributes

The `MaxAttemptsError` exception provides the following attributes:

- **`message`** (str): The error message explaining why the maximum attempts were reached
- **`node_id`** (str): The ID of the node that was being contacted when the max attempts were reached
- **`last_error`** (Exception): The last error that occurred during the final attempt

## Error Handling Context

Understanding the different stages of failure is crucial for proper error handling:

1. **Precheck Errors** (`PrecheckError`): Failures before transaction submission (e.g., insufficient balance, invalid signature)
2. **MaxAttemptsError**: Network/node retry failures during communication
3. **Receipt Status Errors** (`ReceiptStatusError`): Failures after consensus (e.g., smart contract revert)

Many developers assume that if `execute()` doesn't throw, the transaction succeeded. These exceptions explicitly show different stages of failure.

## Example Usage
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to demonstrate the other two error types 👍

We can just explain you can catch a MaxAttemptsError like so

except MaxAttemptsError as e:
print(f"Max attempts reached: {e}")

Then for a full demonstration, add a link to the example.


```python
from hiero_sdk_python import Client, TransferTransaction
from hiero_sdk_python.exceptions import MaxAttemptsError, PrecheckError, ReceiptStatusError

# Create client and transaction
client = Client.forTestnet()
transaction = TransferTransaction()
.addHbarTransfer(sender_account, -1000)
.addHbarTransfer(receiver_account, 1000)

try:
# Execute the transaction
receipt = transaction.execute(client)
print("Transaction executed successfully")

except PrecheckError as e:
# Handle precheck failures (before submission)
print(f"Precheck failed: {e.message}")
print(f"Status: {e.status}")

except MaxAttemptsError as e:
# Handle network/node retry failures
print(f"Max attempts reached on node {e.node_id}: {e.message}")
if e.last_error:
print(f"Last error: {e.last_error}")

# Common recovery strategies:
# 1. Retry with a different node
# 2. Wait and retry the same node
# 3. Check network connectivity

except ReceiptStatusError as e:
# Handle post-consensus failures
print(f"Transaction failed after consensus: {e.message}")
print(f"Status: {e.status}")
```

## Recovery Strategies

When encountering a `MaxAttemptsError`, consider these approaches:

### 1. Retry with Different Node
```python
try:
receipt = transaction.execute(client)
except MaxAttemptsError as e:
# Switch to a different node and retry
client.setNetwork([{"node2.hedera.com:50211": "0.0.2"}])
receipt = transaction.execute(client)
```

### 2. Exponential Backoff
```python
import time

def execute_with_retry(transaction, client, max_retries=3):
for attempt in range(max_retries):
try:
return transaction.execute(client)
except MaxAttemptsError as e:
if attempt == max_retries - 1:
raise
wait_time = 2 ** attempt # 1, 2, 4 seconds
time.sleep(wait_time)
```

### 3. Node Health Check
```python
try:
receipt = transaction.execute(client)
except MaxAttemptsError as e:
print(f"Node {e.node_id} appears unhealthy")
# Implement node health monitoring
# Consider removing the node from rotation temporarily
```

## Best Practices

1. **Always catch MaxAttemptsError separately** from other exceptions to implement appropriate retry logic
2. **Log the node_id** to identify problematic nodes in your network
3. **Implement circuit breakers** to temporarily skip consistently failing nodes
4. **Use exponential backoff** when retrying to avoid overwhelming the network
5. **Monitor last_error** to understand the root cause of failures

## Related Documentation

- [Receipt Status Error](receipt_status_error.md) - Understanding post-consensus failures
- [Receipts](receipts.md) - Working with transaction receipts
- [Error Handling Guide](../common_issues.md) - General error handling strategies
Loading
Loading