ISO GQL Status Codes Reference

Geode implements the complete ISO/IEC 39075:2024 GQL status code system (GQLSTATUS) for standardized error reporting and handling across all client libraries and protocols.

Status Code Format

GQLSTATUS Structure

All GQL status codes follow the five-character format defined by the ISO standard:

GQLXX

Where:

  • GQL = Fixed prefix identifying GQL status codes
  • XX = Two-character code indicating category and specific condition

Status Code Categories

00 - Success
01 - Warning
02 - No Data
21 - Cardinality Violation
22 - Data Exception
23 - Integrity Constraint Violation
24 - Invalid Transaction State
25 - Invalid Transaction Termination
27 - Transaction Rollback
28 - Invalid Authorization Specification
2E - Invalid Connection
42 - Syntax Error or Access Rule Violation

Success Codes

GQL00 - Successful Completion

Code: GQL00 Category: Success Meaning: Query or operation completed successfully with no errors or warnings

Example:

MATCH (p:Person {id: 1}) RETURN p.name

Response:

{
  "status": "GQL00",
  "message": "Successful completion",
  "rows": [{"name": "Alice"}]
}

Handling: No action required, proceed with result processing.

Warning Codes

GQL01 - Warning

Code: GQL01 Subcodes: Multiple warning conditions

Common Warnings:

GQL01001 - Cursor Operation Conflict

Meaning: Cursor operation conflict with concurrent modification

Example Scenario:

-- Transaction 1
START TRANSACTION
DECLARE cursor1 CURSOR FOR MATCH (p:Person) RETURN p
OPEN cursor1

-- Transaction 2 modifies data
CREATE (p:Person {name: 'NewPerson'})

-- Transaction 1 continues
FETCH NEXT FROM cursor1  -- Warning: GQL01001

Handling:

  • Re-execute query if data consistency is critical
  • Accept warning if cursor data can be stale
  • Consider higher isolation level for transaction
GQL01002 - Disconnect Error

Meaning: Disconnect error occurred but operation completed

Handling:

  • Verify operation completion
  • Re-establish connection for subsequent operations
  • Check connection pool health

No Data Codes

GQL02 - No Data

Code: GQL02 Meaning: Query executed successfully but returned no rows

Example:

MATCH (p:Person {email: 'nonexistent@example.com'}) RETURN p

Response:

{
  "status": "GQL02",
  "message": "No data found",
  "rows": []
}

Handling:

  • Not an error condition
  • Check query predicates if data was expected
  • Differentiate from GQL00 (success with data)

GQL02001 - No Additional Data

Meaning: No additional result sets available

Example Scenario:

-- After consuming all result pages
FETCH NEXT FROM cursor1  -- GQL02001

Handling:

  • Normal end-of-results indicator
  • Close cursor or complete pagination

Data Exception Codes

GQL22 - Data Exception

Category: Data validation and type errors

GQL22001 - String Data Right Truncation

Meaning: String value truncated to fit field length

Example:

CREATE (p:Person {name: 'VeryLongNameThatExceedsLimit...'})
-- If name field has max length of 50 characters

Handling:

  • Validate input length before insertion
  • Increase field size if legitimate use case
  • Truncate data explicitly in application
GQL22003 - Numeric Value Out of Range

Meaning: Numeric value exceeds data type bounds

Example:

CREATE (p:Product {quantity: 9999999999999999})
-- If quantity is INT32

Handling:

// Go example
if quantity > math.MaxInt32 {
    return fmt.Errorf("quantity exceeds maximum: %d", math.MaxInt32)
}
GQL22007 - Invalid Datetime Format

Meaning: Datetime string doesn’t match expected format

Example:

CREATE (e:Event {timestamp: '2024-13-45T25:99:99'})  -- Invalid

Valid Formats:

-- ISO 8601 formats
'2024-01-15'                    -- Date
'14:30:00'                      -- Time
'2024-01-15T14:30:00'          -- DateTime
'2024-01-15T14:30:00Z'         -- DateTime with UTC
'2024-01-15T14:30:00-05:00'    -- DateTime with timezone

Handling:

  • Validate datetime strings before insertion
  • Use ISO 8601 format consistently
  • Consider using datetime functions
GQL22008 - Datetime Field Overflow

Meaning: Datetime calculation resulted in overflow

Example:

RETURN datetime('2024-01-01') + duration('P99999Y')

Handling:

  • Validate duration values before arithmetic
  • Check result bounds after calculations
GQL22012 - Division by Zero

Meaning: Attempted division or modulo by zero

Example:

MATCH (p:Product)
RETURN p.price, p.price / p.quantity AS unit_price
-- If quantity = 0

Handling:

-- Add guard clause
MATCH (p:Product)
WHERE p.quantity > 0
RETURN p.price, p.price / p.quantity AS unit_price
# Python example
unit_price = price / quantity if quantity != 0 else None
GQL22018 - Invalid Character Value for Cast

Meaning: String cannot be cast to target type

Example:

RETURN toInteger('not_a_number')  -- GQL22018

Handling:

-- Validate before casting
RETURN CASE
    WHEN value =~ '^[0-9]+$' THEN toInteger(value)
    ELSE NULL
END
GQL22023 - Invalid Parameter Value

Meaning: Parameter value invalid for operation

Example:

MATCH (p:Person)
WHERE p.age > $age  -- $age = 'twenty' (string instead of number)
RETURN p

Handling:

  • Type-check parameters before query execution
  • Use strongly-typed parameter binding
  • Validate input at application boundary

Integrity Constraint Violations

GQL23 - Integrity Constraint Violation

GQL23000 - Integrity Constraint Violation (General)

Meaning: Unspecified integrity constraint violated

Example:

CREATE (p:Person {id: 1, email: 'alice@example.com'})
CREATE (p:Person {id: 1, email: 'bob@example.com'})
-- If id has UNIQUE constraint

Handling:

  • Check constraint definitions
  • Validate data before insertion
  • Handle duplicate key scenarios
GQL23001 - Restrict Violation

Meaning: Foreign key constraint prevents deletion

Example:

-- Person has relationships to Orders
DELETE (p:Person {id: 1})
-- GQL23001 if ON DELETE RESTRICT is enforced

Handling:

-- Use DETACH DELETE to remove relationships
DETACH DELETE (p:Person {id: 1})

-- Or delete relationships first
MATCH (p:Person {id: 1})-[r]-()
DELETE r, p
GQL23505 - Unique Violation

Meaning: Unique constraint violated

Example:

CREATE (u:User {email: 'alice@example.com'})
CREATE (u:User {email: 'alice@example.com'})  -- GQL23505

Handling:

-- Use MERGE for upsert semantics
MERGE (u:User {email: 'alice@example.com'})
ON CREATE SET u.created = datetime()
ON MATCH SET u.accessed = datetime()
# Python error handling
from geode_client.exceptions import ConstraintViolationError

try:
    await conn.execute(
        "CREATE (u:User {email: $email})",
        {"email": email}
    )
except ConstraintViolationError as e:
    if e.status_code == "GQL23505":
        # Handle duplicate email
        logger.warning(f"Email already exists: {email}")
GQL23514 - Check Constraint Violation

Meaning: CHECK constraint condition not satisfied

Example:

-- Assuming CHECK constraint: age >= 0 AND age <= 150
CREATE (p:Person {name: 'Alice', age: 200})  -- GQL23514

Handling:

  • Validate data against constraint rules before insertion
  • Review constraint definitions for reasonableness
  • Provide clear error messages to users

Transaction State Errors

GQL24 - Invalid Transaction State

GQL24000 - Invalid Transaction State (General)

Meaning: Operation not valid in current transaction state

Example:

COMMIT  -- No active transaction

Handling:

  • Track transaction state in application
  • Always pair BEGIN with COMMIT/ROLLBACK
  • Use transaction context managers
# Python - Safe transaction handling
async with db.connection() as tx:
    await tx.begin()
    await tx.execute("CREATE (p:Person {name: 'Alice'})")
    # Automatic commit on success, rollback on exception
GQL25000 - Invalid Transaction Termination

Meaning: Cannot commit or rollback in current state

Example:

START TRANSACTION
-- Connection lost
COMMIT  -- GQL25000

Handling:

  • Implement connection retry logic
  • Re-establish transaction after connection recovery
  • Use savepoints for partial rollback

GQL27 - Transaction Rollback

GQL27000 - Transaction Rollback (General)

Meaning: Transaction rolled back due to error or deadlock

Example:

START TRANSACTION
CREATE (p:Person {id: 1})
-- Deadlock detected with concurrent transaction
-- GQL27000 - Transaction rolled back

Handling:

# Python - Retry on deadlock
max_retries = 3
for attempt in range(max_retries):
    try:
        async with db.connection() as tx:
            await tx.begin()
            await tx.execute(query, params)
        break  # Success
    except TransactionRollbackError as e:
        if "deadlock" in str(e).lower() and attempt < max_retries - 1:
            await asyncio.sleep(0.1 * (2 ** attempt))  # Exponential backoff
        else:
            raise

Syntax and Access Errors

GQL42 - Syntax Error or Access Rule Violation

GQL42000 - Syntax Error or Access Violation (General)

Meaning: Query syntax error or insufficient privileges

Example:

MATCH (p:Person WHERE p.age > 25 RETURN p  -- Missing )

Handling:

  • Validate query syntax before execution
  • Use query builder libraries to prevent syntax errors
  • Check error message for specific syntax issue
GQL42501 - Insufficient Privilege

Meaning: User lacks required permissions

Example:

-- User without CREATE permission
CREATE (p:Person {name: 'Alice'})  -- GQL42501

Handling:

from geode_client.exceptions import InsufficientPrivilegeError

try:
    await conn.execute("CREATE (p:Person {name: 'Alice'})")
except InsufficientPrivilegeError as e:
    logger.error(f"Permission denied: {e.message}")
    # Request access or use different credentials
GQL42601 - Invalid Grant Operation

Meaning: Cannot grant specified privilege

Example:

GRANT CREATE ON GRAPH production TO user1
-- If current user cannot grant this privilege
GQL42704 - Undefined Database Object

Meaning: Referenced object does not exist

Example:

USE GRAPH nonexistent_graph  -- GQL42704

Handling:

  • Verify database object names before use
  • Create objects if they don’t exist
  • Handle missing objects gracefully

Connection Errors

GQL2E - Invalid Connection

GQL2E000 - Connection Exception (General)

Meaning: Connection-level error occurred

Example Scenarios:

  • Network timeout
  • Connection pool exhausted
  • Server unreachable

Handling:

// Go - Connection retry with backoff
func connectWithRetry(url string, maxRetries int) (*gql.DB, error) {
    var db *gql.DB
    var err error

    for i := 0; i < maxRetries; i++ {
        db, err = gql.Open(url)
        if err == nil {
            return db, nil
        }

        if errors.IsConnectionError(err) {
            backoff := time.Duration(100*math.Pow(2, float64(i))) * time.Millisecond
            time.Sleep(backoff)
            continue
        }

        return nil, err  // Non-retryable error
    }

    return nil, fmt.Errorf("failed after %d retries: %w", maxRetries, err)
}
GQL2E001 - Connection Does Not Exist

Meaning: Connection closed or never established

Handling:

  • Check connection status before operations
  • Implement connection health checks
  • Use connection pooling for reliability
# Python - Connection health check
async def ensure_connection(db):
    try:
        async with db.connection() as conn:
            await conn.ping()
    except ConnectionError:
        # Re-establish connection
        await db.reconnect()

Error Handling Best Practices

1. Categorize Errors by Severity

from geode_client.exceptions import GeodeError

def handle_error(e: GeodeError):
    if e.status_code.startswith("GQL00"):
        # Success - no handling needed
        pass
    elif e.status_code.startswith("GQL01"):
        # Warning - log and continue
        logger.warning(f"Warning: {e.message}")
    elif e.status_code.startswith("GQL02"):
        # No data - expected condition
        return []
    elif e.status_code.startswith("GQL22"):
        # Data exception - validation error
        logger.error(f"Invalid data: {e.message}")
        raise ValueError(e.message)
    elif e.status_code.startswith("GQL23"):
        # Constraint violation
        logger.error(f"Constraint violated: {e.message}")
        raise IntegrityError(e.message)
    elif e.status_code.startswith("GQL27"):
        # Transaction rollback - retry
        logger.info(f"Transaction rolled back: {e.message}")
        return "RETRY"
    elif e.status_code.startswith("GQL42"):
        # Syntax or permission error
        logger.error(f"Query error: {e.message}")
        raise SyntaxError(e.message)
    else:
        # Unknown error
        logger.exception(f"Unexpected error: {e.message}")
        raise

2. Implement Retry Logic for Transient Errors

// Go - Retry wrapper
func executeWithRetry(ctx context.Context, db *gql.DB, query string, params map[string]interface{}, maxRetries int) (*gql.Page, error) {
    var page *gql.Page
    var err error

    for attempt := 0; attempt < maxRetries; attempt++ {
        conn, err := db.Connect(ctx)
        if err != nil {
            if errors.IsConnectionError(err) && attempt < maxRetries-1 {
                backoff := time.Duration(100 * math.Pow(2, float64(attempt))) * time.Millisecond
                time.Sleep(backoff)
                continue
            }
            return nil, err
        }
        defer conn.Close()

        page, _, err = conn.Query(ctx, query, params, 100)
        if err == nil {
            return page, nil
        }

        if errors.IsTransactionRollback(err) && attempt < maxRetries-1 {
            backoff := time.Duration(50 * math.Pow(2, float64(attempt))) * time.Millisecond
            time.Sleep(backoff)
            continue
        }

        return nil, err
    }

    return nil, fmt.Errorf("failed after %d attempts: %w", maxRetries, err)
}

3. Log Errors with Context

import logging
import json

logger = logging.getLogger(__name__)

async def execute_query_with_logging(conn, query, params):
    try:
        result = await conn.query(query, params)
        return result
    except GeodeError as e:
        logger.error(
            "Query execution failed",
            extra={
                "status_code": e.status_code,
                "message": e.message,
                "query": query,
                "params": json.dumps(params),
                "stack_trace": str(e)
            }
        )
        raise

4. Validate Input Before Execution

use geode_client::{Client, Value};

fn validate_person(name: &str, age: i32, email: &str) -> Result<(), String> {
    if name.is_empty() {
        return Err("Name cannot be empty".to_string());
    }
    if age < 0 || age > 150 {
        return Err(format!("Invalid age: {}", age));
    }
    if !email.contains('@') {
        return Err(format!("Invalid email: {}", email));
    }
    Ok(())
}

async fn create_person(
    client: &Client,
    name: &str,
    age: i32,
    email: &str
) -> Result<(), Box<dyn std::error::Error>> {
    // Validate before execution
    validate_person(name, age, email)?;

    let mut conn = client.connect().await?;
    conn.execute(
        "CREATE (p:Person {name: $name, age: $age, email: $email})",
        vec![
            ("name", Value::from(name)),
            ("age", Value::from(age)),
            ("email", Value::from(email)),
        ]
    ).await?;

    Ok(())
}

Status Code Quick Reference

By Category

CategoryCode RangeDescription
SuccessGQL00Successful completion
WarningGQL01Warning conditions
No DataGQL02No data found
Data ExceptionGQL22Data validation errors
Constraint ViolationGQL23Integrity constraints
Transaction StateGQL24Invalid transaction state
Transaction TerminationGQL25Cannot commit/rollback
RollbackGQL27Transaction rolled back
Syntax/AccessGQL42Syntax or permission errors
ConnectionGQL2EConnection errors

Common Codes

CodeMeaningAction
GQL00SuccessContinue processing
GQL01WarningLog and continue
GQL02No dataHandle empty result
GQL22003Numeric overflowValidate input range
GQL22007Invalid datetimeCheck format
GQL22012Division by zeroAdd guard clause
GQL23505Unique violationUse MERGE or handle duplicate
GQL27000DeadlockRetry with backoff
GQL42000Syntax errorFix query syntax
GQL42501Insufficient privilegeCheck permissions
GQL2E000Connection errorRetry connection

Troubleshooting Guide

Connection Issues

Problem: GQL2E000 - Connection Exception

Diagnostic Steps:

  1. Verify server is running: geode status
  2. Check network connectivity: ping geode-server
  3. Verify QUIC port (3141) is accessible
  4. Check connection pool status
  5. Review server logs for errors

Solutions:

  • Restart Geode server
  • Check firewall rules for UDP port 3141
  • Increase connection pool size
  • Implement connection retry logic

Query Performance

Problem: Slow queries or timeouts

Diagnostic Steps:

  1. Use EXPLAIN to analyze query plan
  2. Check index usage
  3. Review query complexity
  4. Monitor server resources

Solutions:

-- Add appropriate indexes
CREATE INDEX ON :Person(email)

-- Optimize query with LIMIT
MATCH (p:Person)
WHERE p.age > 25
RETURN p.name, p.email
ORDER BY p.name
LIMIT 100  -- Add limit for large result sets

-- Use PROFILE to measure performance
PROFILE MATCH (p:Person)-[:KNOWS]->(f)
RETURN p.name, count(f) AS friend_count

Transaction Deadlocks

Problem: GQL27000 - Transaction Rollback (Deadlock)

Prevention:

  • Access resources in consistent order
  • Keep transactions short
  • Use appropriate isolation levels
  • Implement retry logic with exponential backoff

Example:

import asyncio
from geode_client import Client, QueryError

async def transfer_with_retry(from_id, to_id, amount, max_retries=3):
    client = Client(host="localhost", port=3141)

    for attempt in range(max_retries):
        async with client.connection() as conn:
            try:
                await conn.begin()

                if from_id < to_id:
                    await conn.query("MATCH (a:Account {id: $id}) RETURN a", {"id": from_id})
                    await conn.query("MATCH (a:Account {id: $id}) RETURN a", {"id": to_id})
                else:
                    await conn.query("MATCH (a:Account {id: $id}) RETURN a", {"id": to_id})
                    await conn.query("MATCH (a:Account {id: $id}) RETURN a", {"id": from_id})

                await conn.execute(
                    "MATCH (a:Account {id: $id}) SET a.balance = a.balance - $amount",
                    {"id": from_id, "amount": amount},
                )
                await conn.execute(
                    "MATCH (a:Account {id: $id}) SET a.balance = a.balance + $amount",
                    {"id": to_id, "amount": amount},
                )

                await conn.commit()
                return
            except QueryError as e:
                await conn.rollback()
                if not str(e).startswith("40502:"):
                    raise
                if attempt < max_retries - 1:
                    await asyncio.sleep(0.1 * (2 ** attempt))
                else:
                    raise

Data Validation Errors

Problem: GQL22* - Data Exception

Prevention:

  • Validate all inputs before database operations
  • Use type-safe parameter binding
  • Define appropriate constraints
  • Implement application-level validation

Example Validation Framework:

from pydantic import BaseModel, EmailStr, Field
from datetime import datetime

class PersonCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    age: int = Field(..., ge=0, le=150)
    email: EmailStr
    birth_date: datetime

    class Config:
        json_schema_extra = {
            "example": {
                "name": "Alice Smith",
                "age": 30,
                "email": "[email protected]",
                "birth_date": "1994-01-15T00:00:00Z"
            }
        }

async def create_person(person: PersonCreate):
    # Pydantic validation happens automatically
    # Safe to execute query with validated data
    async with db.connection() as conn:
        await conn.execute(
            """
            CREATE (p:Person {
                name: $name,
                age: $age,
                email: $email,
                birth_date: $birth_date
            })
            """,
            person.dict()
        )

Client Library Integration

Go Client

import (
    "gitlab.com/devnw/codepros/geode-client-go/errors"
)

// Error type checking
if errors.IsConstraintViolation(err) {
    // Handle constraint violation
}
if errors.IsConnectionError(err) {
    // Handle connection error
}

// Status code access
if gqlErr, ok := err.(errors.GQLError); ok {
    statusCode := gqlErr.StatusCode()  // e.g., "GQL23505"
    message := gqlErr.Message()
}

Python Client

from geode_client.exceptions import (
    GeodeError,
    ConstraintViolationError,
    ConnectionError,
    TransactionRollbackError
)

try:
    await conn.execute(query, params)
except ConstraintViolationError as e:
    print(f"Constraint violation: {e.status_code} - {e.message}")
except TransactionRollbackError as e:
    print(f"Transaction rolled back: {e.status_code}")
except ConnectionError as e:
    print(f"Connection error: {e.status_code}")
except GeodeError as e:
    print(f"Geode error: {e.status_code} - {e.message}")

Rust Client

use geode_client::{Error, ErrorKind};

match conn.execute(query, params).await {
    Ok(_) => println!("Success"),
    Err(Error::ConstraintViolation { code, message }) => {
        eprintln!("Constraint violation {}: {}", code, message);
    }
    Err(Error::Connection(msg)) => {
        eprintln!("Connection error: {}", msg);
    }
    Err(Error::TransactionRollback { code }) => {
        eprintln!("Transaction rolled back: {}", code);
    }
    Err(e) => eprintln!("Error: {:?}", e),
}

Next Steps

  1. Implement Error Handling - Add proper error handling to all database operations
  2. Add Retry Logic - Implement retries for transient errors (deadlocks, connection issues)
  3. Validate Inputs - Validate all data before database operations
  4. Monitor Errors - Track error rates and types in production
  5. Review Logs - Regularly review error logs for patterns
  6. Test Error Scenarios - Include error cases in test suite

Related Documentation:


Last Updated: January 2026 Based on: ISO/IEC 39075:2024 GQL Standard Status: Production-ready - 100% GQL compliance