Error Handling

4 min read

The SDK provides a comprehensive exception system to help you handle errors gracefully. Instead of returning error arrays or null values, the SDK throws specific exceptions that allow you to implement robust error handling strategies.

Exception hierarchy

All SDK exceptions extend from AbstractNotionException, which provides a consistent interface for error handling:

AbstractNotionException
├── HttpResponseException (HTTP-level errors)
│   └── ApiResponseException (Notion API errors)
├── RequestTimeoutException (Request timeouts)
└── Various resource-specific exceptions

Types of exceptions

1. ApiResponseException

This is the most common exception you'll encounter. It's thrown when the Notion API returns an error response (4xx or 5xx status codes).

<?php

use Brd6\NotionSdkPhp\Exception\ApiResponseException;
use Brd6\NotionSdkPhp\Client;
use Brd6\NotionSdkPhp\ClientOptions;

$options = (new ClientOptions())->setAuth('your_token');
$notion = new Client($options);

try {
    $page = $notion->pages()->retrieve('invalid_page_id');
} catch (ApiResponseException $e) {
    // Handle Notion API errors
    echo "API Error: " . $e->getMessage() . "\n";
    echo "Error Code: " . $e->getMessageCode() . "\n";
    echo "HTTP Status: " . $e->getCode() . "\n";
}

2. HttpResponseException

Thrown for HTTP-level errors that aren't specific Notion API errors (network issues, server errors, etc.).

<?php

use Brd6\NotionSdkPhp\Exception\HttpResponseException;

try {
    $page = $notion->pages()->retrieve('page_id');
} catch (HttpResponseException $e) {
    // Handle HTTP-level errors
    echo "HTTP Error: " . $e->getMessage() . "\n";
    echo "Status Code: " . $e->getCode() . "\n";
    echo "Headers: " . json_encode($e->getHeaders()) . "\n";
}

3. RequestTimeoutException

Thrown when requests exceed the configured timeout period.

<?php

use Brd6\NotionSdkPhp\Exception\RequestTimeoutException;

try {
    $page = $notion->pages()->retrieve('page_id');
} catch (RequestTimeoutException $e) {
    // Handle timeout errors
    echo "Request timed out: " . $e->getMessage() . "\n";
    // Maybe retry with exponential backoff
}

Accessing error details

ApiResponseException properties

When catching ApiResponseException, you can access detailed error information:

<?php

use Brd6\NotionSdkPhp\Exception\ApiResponseException;

try {
    $page = $notion->pages()->retrieve('invalid_page_id');
} catch (ApiResponseException $e) {
    // Notion-specific error code (e.g., "object_not_found", "validation_error")
    $errorCode = $e->getMessageCode();

    // Human-readable error message
    $message = $e->getMessage();

    // HTTP status code (e.g., 404, 400, 401)
    $httpStatus = $e->getCode();

    // Notion API status (usually same as HTTP status)
    $notionStatus = $e->getStatus();

    // Raw response data from Notion API
    $rawData = $e->getRawData();

    // Response headers
    $headers = $e->getHeaders();

    echo "Error: {$message}\n";
    echo "Code: {$errorCode}\n";
    echo "HTTP Status: {$httpStatus}\n";
}

Using error code constants

To avoid using magic strings when checking for specific error types, use the NotionErrorCodeConstant class:

<?php

use Brd6\NotionSdkPhp\Exception\ApiResponseException;
use Brd6\NotionSdkPhp\Constant\NotionErrorCodeConstant;

try {
    $page = $notion->pages()->retrieve('page_id');
} catch (ApiResponseException $e) {
    switch ($e->getMessageCode()) {
        case NotionErrorCodeConstant::OBJECT_NOT_FOUND:
            echo "The page was not found or you don't have access to it.\n";
            break;

        case NotionErrorCodeConstant::UNAUTHORIZED:
            echo "Invalid or missing authentication token.\n";
            break;

        case NotionErrorCodeConstant::RATE_LIMITED:
            echo "Too many requests. Please wait before retrying.\n";
            // Implement exponential backoff
            break;

        case NotionErrorCodeConstant::VALIDATION_ERROR:
            echo "Request validation failed: " . $e->getMessage() . "\n";
            break;

        case NotionErrorCodeConstant::INTERNAL_SERVER_ERROR:
            echo "Notion server error. Please try again later.\n";
            break;

        default:
            echo "Unknown error: " . $e->getMessage() . "\n";
    }
}

Available error codes

The SDK defines constants for all known Notion API error codes:

Client Errors (4xx)

  • UNAUTHORIZED - Invalid or missing authentication
  • RESTRICTED_RESOURCE - Insufficient permissions
  • OBJECT_NOT_FOUND - Resource not found or inaccessible
  • RATE_LIMITED - Too many requests
  • INVALID_JSON - Malformed JSON in request
  • INVALID_REQUEST_URL - Invalid API endpoint
  • INVALID_REQUEST - Invalid request parameters
  • VALIDATION_ERROR - Request validation failed
  • MISSING_VERSION - Missing Notion-Version header
  • CONFLICT_ERROR - Resource conflict

Server Errors (5xx)

  • INTERNAL_SERVER_ERROR - Server-side error
  • SERVICE_UNAVAILABLE - Service temporarily unavailable
  • DATABASE_CONNECTION_UNAVAILABLE - Database connection issues

Client-Side Errors

  • REQUEST_TIMEOUT - Request timeout
  • RESPONSE_ERROR - HTTP response error

Comprehensive error handling example

Here's a robust error handling pattern that covers all exception types:

<?php

use Brd6\NotionSdkPhp\Client;
use Brd6\NotionSdkPhp\ClientOptions;
use Brd6\NotionSdkPhp\Exception\ApiResponseException;
use Brd6\NotionSdkPhp\Exception\HttpResponseException;
use Brd6\NotionSdkPhp\Exception\RequestTimeoutException;
use Brd6\NotionSdkPhp\Constant\NotionErrorCodeConstant;

function retrievePageSafely(Client $notion, string $pageId): ?array
{
    try {
        $page = $notion->pages()->retrieve($pageId);
        return $page->toArray();

    } catch (ApiResponseException $e) {
        // Handle Notion API specific errors
        switch ($e->getMessageCode()) {
            case NotionErrorCodeConstant::OBJECT_NOT_FOUND:
                echo "Page not found: {$pageId}\n";
                return null;

            case NotionErrorCodeConstant::UNAUTHORIZED:
                echo "Authentication failed. Check your token.\n";
                throw $e; // Re-throw for critical errors

            case NotionErrorCodeConstant::RATE_LIMITED:
                echo "Rate limited. Implementing backoff...\n";
                sleep(60); // Simple backoff
                return retrievePageSafely($notion, $pageId); // Retry

            case NotionErrorCodeConstant::VALIDATION_ERROR:
                echo "Validation error: " . $e->getMessage() . "\n";
                return null;

            default:
                echo "API error: " . $e->getMessage() . "\n";
                return null;
        }

    } catch (RequestTimeoutException $e) {
        echo "Request timed out. Retrying...\n";
        return retrievePageSafely($notion, $pageId); // Retry once

    } catch (HttpResponseException $e) {
        echo "HTTP error: " . $e->getMessage() . "\n";
        return null;

    } catch (\Exception $e) {
        // Catch any other unexpected errors
        echo "Unexpected error: " . $e->getMessage() . "\n";
        return null;
    }
}

// Usage
$options = (new ClientOptions())->setAuth('your_token');
$notion = new Client($options);

$pageData = retrievePageSafely($notion, 'your_page_id');

if ($pageData !== null) {
    echo "Successfully retrieved page data\n";
} else {
    echo "Failed to retrieve page\n";
}
Did this answer your question?