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
| Category | Code Range | Description |
|---|---|---|
| Success | GQL00 | Successful completion |
| Warning | GQL01 | Warning conditions |
| No Data | GQL02 | No data found |
| Data Exception | GQL22 | Data validation errors |
| Constraint Violation | GQL23 | Integrity constraints |
| Transaction State | GQL24 | Invalid transaction state |
| Transaction Termination | GQL25 | Cannot commit/rollback |
| Rollback | GQL27 | Transaction rolled back |
| Syntax/Access | GQL42 | Syntax or permission errors |
| Connection | GQL2E | Connection errors |
Common Codes
| Code | Meaning | Action |
|---|---|---|
| GQL00 | Success | Continue processing |
| GQL01 | Warning | Log and continue |
| GQL02 | No data | Handle empty result |
| GQL22003 | Numeric overflow | Validate input range |
| GQL22007 | Invalid datetime | Check format |
| GQL22012 | Division by zero | Add guard clause |
| GQL23505 | Unique violation | Use MERGE or handle duplicate |
| GQL27000 | Deadlock | Retry with backoff |
| GQL42000 | Syntax error | Fix query syntax |
| GQL42501 | Insufficient privilege | Check permissions |
| GQL2E000 | Connection error | Retry connection |
Troubleshooting Guide
Connection Issues
Problem: GQL2E000 - Connection Exception
Diagnostic Steps:
- Verify server is running:
geode status - Check network connectivity:
ping geode-server - Verify QUIC port (3141) is accessible
- Check connection pool status
- 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:
- Use EXPLAIN to analyze query plan
- Check index usage
- Review query complexity
- 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
- Implement Error Handling - Add proper error handling to all database operations
- Add Retry Logic - Implement retries for transient errors (deadlocks, connection issues)
- Validate Inputs - Validate all data before database operations
- Monitor Errors - Track error rates and types in production
- Review Logs - Regularly review error logs for patterns
- 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