Exception Handling

The monday-client library provides comprehensive error handling through custom exceptions that help you understand and respond to different types of API errors. This page covers all available exceptions, when they occur, and how to handle them effectively.

Exception Overview

All custom exceptions in monday-client inherit from Python’s base Exception class and provide additional context about API errors. They are designed to give you actionable information for debugging and error recovery.

Exception Summary

Exception

Trigger Condition

Key Attributes

MondayAPIError

General API communication errors

json (API response data)

ComplexityLimitExceeded

GraphQL query too complex

reset_in, json

MutationLimitExceeded

Too many mutations per minute

reset_in, json

PaginationError

Item pagination failures

json (pagination context)

QueryFormatError

Malformed GraphQL queries

json (format details)

Exception Details

MondayAPIError

class MondayAPIError(message, json=None)[source]

Bases: Exception

Exception raised when an error occurs during API communication with monday.com.

Parameters:
message

Explanation of the error.

json

JSON data returned by the API, if available.

When it occurs: - Network connectivity issues - Invalid API keys or authentication failures - Server-side errors (5xx responses) - Malformed requests that don’t fit other specific categories

Example usage:

import asyncio
from monday import MondayClient, MondayAPIError

async def handle_api_errors():
   client = MondayClient(api_key='your_api_key')

   try:
      boards = await client.boards.query(board_ids=[123456789])
   except MondayAPIError as e:
      print(f'API Error: {e}')

      # Access additional error context
      if e.json:
         print(f'Error details: {e.json}')

         # Check for specific error types
         if 'errors' in e.json:
            for error in e.json['errors']:
               print(f'- {error.get("message", "Unknown error")}')

asyncio.run(handle_api_errors())

ComplexityLimitExceeded

class ComplexityLimitExceeded(message, reset_in, json=None)[source]

Bases: Exception

Exception raised when the complexity limit is exceeded.

Parameters:
message

Explanation of the error.

reset_in

Time in seconds until the complexity limit is reset.

json

JSON data returned by the API, if available.

When it occurs: - GraphQL query requests too much data in a single call - Deeply nested queries with many relationships - Queries that would consume excessive server resources

Understanding complexity limits: Monday.com limits the computational complexity of GraphQL queries to ensure fair usage. Complex queries with many nested fields or large result sets can exceed these limits.

Example usage:

import asyncio
from monday import MondayClient, ComplexityLimitExceeded

async def handle_complexity_limits():
   client = MondayClient(api_key='your_api_key')

   try:
      # This might be too complex if requesting many boards with full details
      boards = await client.boards.query(
         board_ids=list(range(1000000, 1000100)),  # 100 boards
         fields='id name description owners { id name email } groups { id title color items { id name column_values { id text } } }'
      )
   except ComplexityLimitExceeded as e:
      print(f'Query too complex: {e}')
      print(f'Retry in {e.reset_in} seconds')

      # The client automatically handles retries, but you can implement custom logic
      await asyncio.sleep(e.reset_in)

      # Try a simpler query
      boards = await client.boards.query(
         board_ids=[1000000],  # Just one board
         fields='id name description'  # Fewer fields
      )

asyncio.run(handle_complexity_limits())

MutationLimitExceeded

class MutationLimitExceeded(message, reset_in, json=None)[source]

Bases: Exception

Exception raised when the mutation per minute limit is exceeded.

Parameters:
message

Explanation of the error.

reset_in

Time in seconds until the rate limit is reset.

json

JSON data returned by the API, if available.

When it occurs: - Too many create, update, or delete operations per minute - Exceeding monday.com’s mutation rate limits - Bulk operations that happen too quickly

Rate limit details: Monday.com enforces rate limits on mutations (data-changing operations) to prevent abuse and ensure system stability. The exact limits depend on your plan and current usage.

Example usage:

import asyncio
from monday import MondayClient, MutationLimitExceeded
from monday.types import TextInput

async def handle_mutation_limits():
   client = MondayClient(api_key='your_api_key')

   items_to_update = [123456789, 123456790, 123456791]

   for item_id in items_to_update:
      try:
         await client.items.change_column_values(
            item_id=item_id,
            column_values=[TextInput('text', f'Updated item {item_id}')]
         )
      except MutationLimitExceeded as e:
         print(f'Rate limit exceeded: {e}')
         print(f'Waiting {e.reset_in} seconds before retrying...')

         # Wait for rate limit to reset
         await asyncio.sleep(e.reset_in)

         # Retry the operation
         await client.items.change_column_values(
            item_id=item_id,
            column_values=[TextInput('text', f'Updated item {item_id}')]
         )

asyncio.run(handle_mutation_limits())

PaginationError

class PaginationError(message, json=None)[source]

Bases: Exception

Exception raised when item pagination fails.

Parameters:
message

Explanation of the error.

json

JSON data returned by the API, if available.

When it occurs: - Invalid pagination cursors - Attempting to paginate beyond available data - Corrupted pagination state during large data retrievals

Example usage:

import asyncio
from monday import MondayClient, PaginationError

async def handle_pagination_errors():
   client = MondayClient(api_key='your_api_key')

   try:
      # Get items with pagination
      item_lists = await client.boards.get_items(
         board_ids=[123456789],
         limit=50
      )

      for item_list in item_lists:
         print(f'Board {item_list.board_id}: {len(item_list.items)} items')

   except PaginationError as e:
      print(f'Pagination failed: {e}')

      # Try without pagination for smaller datasets
      item_lists = await client.boards.get_items(
         board_ids=[123456789],
         limit=10  # Smaller limit
      )

asyncio.run(handle_pagination_errors())

QueryFormatError

class QueryFormatError(message, json=None)[source]

Bases: Exception

Exception raised when a query is improperly formatted.

Parameters:
message

Explanation of the error.

json

JSON data returned by the API, if available.

When it occurs: - Malformed GraphQL query syntax - Invalid field names or structures - Incorrect query parameters or arguments

Example usage:

import asyncio
from monday import MondayClient, QueryFormatError

async def handle_query_format_errors():
   client = MondayClient(api_key='your_api_key')

   try:
      # This might cause a format error if fields are invalid
      boards = await client.boards.query(
         board_ids=[123456789],
         fields='invalid_field { also_invalid }'  # Bad field names
      )
   except QueryFormatError as e:
      print(f'Query format error: {e}')

      if e.json and 'errors' in e.json:
         for error in e.json['errors']:
            print(f'GraphQL Error: {error.get("message")}')

      # Use valid fields instead
      boards = await client.boards.query(
         board_ids=[123456789],
         fields='id name state'  # Valid fields
      )

asyncio.run(handle_query_format_errors())

Best Practices

General Error Handling Strategy

  1. Always use try-catch blocks for API operations:

    from monday import MondayClient, MondayAPIError
    
    async def robust_api_call():
       client = MondayClient(api_key='your_api_key')
    
       try:
          result = await client.boards.query(board_ids=[123456789])
          return result
       except MondayAPIError as e:
          # Log the error for debugging
          print(f'API call failed: {e}')
    
          # Return None or empty list instead of crashing
          return []
    
  2. Handle specific exceptions differently:

from monday import (
   MondayClient,
   MondayAPIError,
   ComplexityLimitExceeded,
   MutationLimitExceeded
)

async def comprehensive_error_handling():
   client = MondayClient(api_key='your_api_key')

   try:
      boards = await client.boards.query(board_ids=[123456789])
   except ComplexityLimitExceeded as e:
      # Simplify the query
      print(f'Query too complex, simplifying...')
      boards = await client.boards.query(
         board_ids=[123456789],
         fields='id name'
      )
   except MutationLimitExceeded as e:
      # Wait and retry
      print(f'Rate limited, waiting {e.reset_in} seconds...')
      await asyncio.sleep(e.reset_in)
      boards = await client.boards.query(board_ids=[123456789])
   except MondayAPIError as e:
      # General error handling
      print(f'API error: {e}')
      boards = []

Rate Limiting and Retries

The monday-client automatically handles rate limiting with built-in retry logic, but you can implement additional strategies:

import asyncio
from monday import MondayClient, ComplexityLimitExceeded, MutationLimitExceeded

async def retry_with_backoff(client, max_retries=3):
   """Retry an operation with exponential backoff."""
   for attempt in range(max_retries):
      try:
         return await client.items.create(
            board_id=123456789,
            item_name='New Item'
         )
      except (ComplexityLimitExceeded, MutationLimitExceeded) as e:
         if attempt == max_retries - 1:
            raise  # Re-raise on final attempt
         wait_time = e.reset_in if hasattr(e, 'reset_in') else (2 ** attempt)
         print(f'Attempt {attempt + 1} failed, waiting {wait_time} seconds...')
         await asyncio.sleep(wait_time)

async def main():
   client = MondayClient(api_key='your_api_key')
   # Retry with backoff
   new_item = await retry_with_backoff(client)

asyncio.run(main())

Query Optimization

To avoid ComplexityLimitExceeded errors:

async def main():
   # Too complex - requests everything at once
   try:
      boards = await client.boards.query(
         board_ids=[987654321, 876543210, 765432109, 654321098, 543210987],
         fields='id name description owners { id name email } groups { id title color items { id name column_values { id text } subitems { id name } } }'
      )
   except ComplexityLimitExceeded:
      pass

   # Better - request fewer boards and simpler fields
   boards = await client.boards.query(
      board_ids=[987654321, 876543210, 765432109],  # Fewer boards
      fields='id name description'  # Essential fields only
   )

main()

Logging and Debugging

Enable detailed logging to debug exceptions:

import logging
from monday import MondayClient, MondayAPIError

# Enable debug logging
logging.basicConfig(level=logging.DEBUG)
monday_logger = logging.getLogger('monday')
monday_logger.setLevel(logging.DEBUG)

# Add a handler if none exists
if not monday_logger.handlers:
   handler = logging.StreamHandler()
   formatter = logging.Formatter(
      '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
   )
   handler.setFormatter(formatter)
   monday_logger.addHandler(handler)

client = MondayClient(api_key='your_api_key')

async def main():
   return await client.boards.query(board_ids=[123456789])

try:
   boards = asyncio.run(main())
except MondayAPIError as e:
   # Detailed error information will be logged automatically
   print(f'Operation failed: {e}')

Common Error Scenarios

Authentication Issues

Symptoms: - MondayAPIError with authentication-related messages - HTTP 401 Unauthorized responses

Solutions:

from monday import MondayClient, MondayAPIError

async def check_authentication():
   try:
      client = MondayClient(api_key='your_api_key')
      # Simple query to test authentication
      boards = await client.boards.query(board_ids=[123456789], fields='id')
   except MondayAPIError as e:
      if 'unauthorized' in str(e).lower():
         print('Authentication failed. Check your API key.')
         print('Get your API key from: https://monday.com/developers/api')
      else:
         print(f'Other API error: {e}')

Network Issues

Symptoms: - MondayAPIError with network-related messages - Timeouts or connection errors

Solutions:

import aiohttp
from monday import MondayClient, MondayAPIError, Config

async def handle_network_issues():
   # Configure longer timeout for slow networks
   config = Config(
      api_key='your_api_key',
      timeout=60  # 60 second timeout instead of default 30
   )
   client = MondayClient(config)

   try:
      boards = await client.boards.query(board_ids=[123456789])
   except MondayAPIError as e:
      if 'timeout' in str(e).lower():
         print('Request timed out. Try again or check your network.')
      elif 'connection' in str(e).lower():
         print('Connection failed. Check your internet connection.')
      else:
         raise

Invalid Data Access

Symptoms: - MondayAPIError when accessing non-existent boards/items - Permission-related errors

Solutions:

from monday import MondayClient, MondayAPIError

async def safe_data_access():
   client = MondayClient(api_key='your_api_key')

   try:
      boards = await client.boards.query(board_ids=[999999999])  # Non-existent board
   except MondayAPIError as e:
      if 'not found' in str(e).lower():
         print('Board not found or no access permission')
         return []
      elif 'permission' in str(e).lower():
         print('Insufficient permissions to access this board')
         return []
      else:
         raise

# Alternative: Check if boards exist first
async def check_board_access():
   client = MondayClient(api_key='your_api_key')

   try:
      # Get all accessible boards first
      all_boards = await client.boards.query(board_ids=[], fields='id name')
      accessible_ids = [board.id for board in all_boards]

      # Only query boards you have access to
      target_ids = [123456789, 987654321]
      valid_ids = [id for id in target_ids if str(id) in accessible_ids]

      if valid_ids:
         boards = await client.boards.query(board_ids=valid_ids)
         return boards
      else:
         print('No accessible boards found')
         return []

   except MondayAPIError as e:
      print(f'Error checking board access: {e}')
      return []

Troubleshooting Guide

Exception Not Being Caught

Problem: Exceptions are not being caught by your try-catch blocks.

Solution: Make sure you’re importing the correct exceptions:

# Correct - import specific exceptions
from monday.exceptions import MondayAPIError, ComplexityLimitExceeded

async def example_function():
   # Incorrect - won't catch monday-client exceptions
   try:
      result = await client.boards.query(board_ids=[123])
   except Exception as e:  # Too generic
      pass

   # Correct - catch specific exceptions
   try:
      result = await client.boards.query(board_ids=[123])
   except MondayAPIError as e:
      print(f'Monday API error: {e}')
   except Exception as e:  # Catch-all for unexpected errors
      print(f'Unexpected error: {e}')

Unclear Error Messages

Problem: Error messages don’t provide enough context.

Solution: Access the json attribute for detailed error information:

from monday import MondayClient, MondayAPIError
import json

async def debug_errors():
   try:
      boards = await client.boards.query(board_ids=[123456789])
   except MondayAPIError as e:
      print(f'Error message: {e}')

      if e.json:
         # Pretty print the full error context
         print('Full error details:')
         print(json.dumps(e.json, indent=2))

         # Extract specific error information
         if 'errors' in e.json:
            for error in e.json['errors']:
               print(f'GraphQL Error: {error.get("message")}')
               if 'path' in error:
                  print(f'Error path: {error["path"]}')

Frequent Rate Limiting

Problem: Constantly hitting rate limits.

Solutions:

  1. Reduce request frequency:

    import asyncio
    from monday import MondayClient
    
    async def batch_operations_with_delay():
       client = MondayClient(api_key='your_api_key')
    
       items_to_update = [123, 456, 789, 101112]
    
       for i, item_id in enumerate(items_to_update):
          await client.items.change_column_values(
             item_id=item_id,
             column_values=[TextInput('text', f'Update {i}')]
          )
    
          # Add delay between operations
          if i < len(items_to_update) - 1:
             await asyncio.sleep(1)  # 1 second delay
    
  2. Batch operations when possible:

async def batch_example():
   # Individual requests (more likely to hit limits)
   for item_id in [123, 456, 789]:
      await client.items.change_column_values(
         item_id=item_id,
         column_values=[TextInput('text', 'Updated')]
      )

   # Fewer, larger requests
   all_items = await client.items.query(
      item_ids=[123, 456, 789],
      fields='id name'
   )

See also

  • Usage - Basic usage examples and patterns

  • Configuration - Configuration options including timeouts and retries

  • MondayClient - MondayClient API reference