Troubleshooting
Critical Issues
This guide covers common issues encountered when working with Grapa and GrapaPy, along with their solutions and debugging techniques.
Installation and Dependency Issues
Python Extension Installation Failures
"Missing system dependencies" Error
Problem: pip install grapapy fails with dependency errors.
What this means: GrapaPy requires system-level dependencies that pip cannot install automatically. You must install these dependencies manually before running pip install grapapy.
Solutions by Platform:
Linux - Automatic (Recommended):
# Install Grapa CLI with automatic dependency installation
python3 install-grapa-0.1.56.py --install-dependencies
# Then install Python extension
pip3 install grapapy
Linux - Manual:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install build-essential python3-dev libssl-dev libx11-dev libxext-dev cmake
# CentOS/RHEL/Amazon Linux
sudo yum groupinstall 'Development Tools'
sudo yum install gcc-c++ python3-devel openssl-devel libX11-devel libXext-devel cmake
# Fedora
sudo dnf groupinstall 'Development Tools'
sudo dnf install python3-devel openssl-devel libX11-devel libXext-devel cmake
# Then install Python extension
pip3 install grapapy
macOS - Automatic (Recommended):
# Install Grapa CLI with automatic dependency installation
python3 install-grapa-0.1.56.py --install-dependencies
# Then install Python extension
pip3 install grapapy
macOS - Manual:
# Install Xcode Command Line Tools
xcode-select --install
# Then install Python extension
pip3 install grapapy
Windows - Manual Only:
# 1. Install Visual Studio 2022 or Build Tools for Visual Studio 2022
# Download from: https://visualstudio.microsoft.com/downloads/
# Ensure "Desktop development with C++" workload is selected
# 2. Run from "x64 Native Tools Command Prompt for VS 2022"
pip install grapapy
Note: Windows does not support automatic dependency installation. Visual Studio must be installed manually.
Ubuntu 24.04+ "externally-managed-environment" Error
Problem: pip install grapapy fails with externally-managed-environment error.
Solution:
# Use --break-system-packages flag
pip3 install grapapy --break-system-packages
"undefined symbol" Error on Linux
Problem: ImportError: undefined symbol: _ZN17GrapaLibraryEvent17HasActiveTryBlockEP10GrapaNames
Solution: This indicates an outdated distribution package. The issue is resolved in Grapa 0.1.56+ with updated static libraries.
CMake Build Failures
Windows: "Visual Studio Compiler Required"
Problem: CMake fails with compiler detection errors.
Solution: 1. Install Visual Studio 2022 or Build Tools for Visual Studio 2022 2. Ensure MSVC compiler is selected in CMake 3. Verify Windows SDK is installed
Linux: "OpenSSL Library Not Found"
Problem: CMake fails to find OpenSSL libraries.
Solution:
# Ubuntu/Debian
sudo apt-get install libssl-dev
# CentOS/RHEL/Amazon Linux
sudo yum install openssl-devel
macOS: "Xcode Command Line Tools Required"
Problem: CMake fails on macOS.
Solution:
xcode-select --install
See Also: - Getting Started - Debugging - Comprehensive debugging system for troubleshooting - Migration Tips for Python Users - Python Integration Guide
Common Error Patterns
{"error":-1} Responses
Problem: Operations return {"error":-1} instead of expected results.
Common Causes: 1. Namespace Issues: Objects created in local namespace are lost between calls 2. Missing Global Variables: Objects not properly stored in global namespace 3. Type Conversion Issues: Binary data not converted to appropriate types
Solutions:
Namespace Issues
# ❌ Problem: Object lost between calls (when using parameters)
xy.eval('table = {}.table("ROW")', {'x': 5})
xy.eval('table.mkfield("name", "STR")') # Error: table not found
# ✅ Solution: Use global namespace for parameterized execution
xy.eval('$global.table = {}.table("ROW")', {'x': 5})
xy.eval('table.mkfield("name", "STR")') # Success
# ✅ Alternative: Direct execution (no parameters) - variables persist automatically
xy.eval('table = {}.table("ROW")')
xy.eval('table.mkfield("name", "STR")') # Success
Type Conversion Issues
# ❌ Problem: Binary data not converted
result = xy.eval('table.get("user1", "name")') # Binary data
# ✅ Solution: Convert to appropriate type
result = xy.eval('table.get("user1", "name").str()') # String
Object Not Found Errors
Problem: Variables or objects are not found when expected.
Common Causes: 1. Local Namespace Clearing: Variables created in one call are lost in the next 2. Missing Global Declaration: Objects not stored in global namespace 3. Incorrect Variable Names: Typos or incorrect variable references
Solutions:
# ✅ Always use $global for persistent objects
xy.eval('$global.fs = $file()')
xy.eval('$global.table = {}.table("ROW")')
# ✅ Use variable names directly after global declaration
xy.eval('fs.set("test.txt", "content")')
xy.eval('table.mkfield("name", "STR")')
Field Type Issues
Problem: Integer fields are created as string types instead of integer types.
Common Cause: Incorrect field creation syntax for integer fields.
Solutions:
# ❌ Problem: May create string fields
xy.eval('table.mkfield("age", "INT", "FIX", 4)')
# ✅ Solution: Use without explicit mode for integers
xy.eval('table.mkfield("age", "INT")')
Syntax Errors
Problem: Grapa code fails to parse or execute.
Common Causes:
1. Incorrect Echo Syntax: Using function calls instead of method calls
2. Wrong Loop Syntax: Using for loops instead of while loops
3. Missing Parentheses: String concatenation not properly wrapped
Solutions:
Echo Syntax
/* ❌ Incorrect */
echo("Hello World");
/* ✅ Correct */
"Hello World".echo();
Loop Syntax
/* ❌ Incorrect */
for i in 1..10 {
echo("Item " + i);
}
/* ✅ Correct */
i = 1;
while (i <= 10) {
("Item " + i.str()).echo();
i = i + 1;
}
String Concatenation
/* ❌ Incorrect */
"Name: " + name.str() + ", Age: " + age.str().echo();
/* ✅ Correct */
("Name: " + name.str() + ", Age: " + age.str()).echo();
Array and Object Access Issues
Problem: Confusion about when to use bracket notation vs .get() method.
Solution: Understand the distinction between different object types:
Arrays and Lists
/* ✅ Arrays support bracket notation */
element = ["a", "b", "c"];
value = element[1]; /* Returns "b" */
/* Note: .get() method is now supported for arrays - can use bracket notation or .get() */
/* ✅ Lists support bracket notation and .getname() */
obj = {"a": 11, "b": 22, "c": 33};
value = obj["b"]; /* Returns 22 */
name = obj.getname(1); /* Returns "b" */
/* Note: .get() method not supported for lists - use bracket notation */
$file and $TABLE Objects
/* ✅ ALWAYS use .getfield() and .setfield() for $file and $TABLE objects */
files = fs.ls();
file_info = files.getfield(0);
table_data = table.getfield("user1", "name");
/* ❌ Avoid bracket notation for $file and $TABLE objects */
file_info = files[0]; /* May not work reliably */
Property Names with Hyphens
/* ⚠️ IMPORTANT: Hyphens in property names require quotes */
/* The hyphen (-) is interpreted as a subtraction operator */
/* ❌ Problem: Hyphen interpreted as subtraction */
config = {ab:3, "a-b":4, a-b:5}; /* a-b becomes 5 (math operation) */
config.a-b; /* This is interpreted as config.a - b (subtraction) */
/* ✅ Solution: Use quotes for hyphenated names */
config = {ab:3, "a-b":4};
config["a-b"]; /* 4 (correct) */
config."a-b"; /* 4 (also correct) */
/* ✅ Also works for function calls */
config = {ab:3, "a-b":op(){44;}};
config."a-b"(); /* 44 */
Debugging Techniques
Check Object Types
# Check what type an object is
xy.eval('$global.debug_obj = some_operation()')
obj_type = xy.eval('debug_obj.type()')
print(f"Object type: {obj_type}")
Verify Global Variables
# Test if global variable exists
xy.eval('$global.test_var = "test"')
result = xy.eval('test_var')
print(f"Global variable: {result}")
Step-by-Step Debugging
# Test each step individually
xy.eval('$global.fs = $file()')
print("File object created")
xy.eval('fs.set("test.txt", "Hello")')
print("File written")
content = xy.eval('fs.get("test.txt").str()')
print(f"File content: {content}")
Error Pattern Analysis
# Check for specific error patterns
result = xy.eval('some_operation()')
if result == {"error":-1}:
print("Operation failed with error -1")
elif result.type() == "$ERR":
print("Operation returned error type")
else:
print(f"Operation succeeded: {result}")
GrapaPy Integration Issues
Namespace Persistence
Problem: Objects don't persist between Python calls.
Solution: Always use $global for objects that need to persist:
# ✅ Correct pattern
xy.eval('$global.table = {}.table("ROW")')
xy.eval('table.mkfield("name", "STR", "VAR")')
xy.eval('table.set("user1", "John", "name")')
Type Conversion
Problem: Binary data returned instead of Python types.
Solution: Use Grapa's conversion methods:
# ✅ Convert binary data to Python types
name = xy.eval('table.get("user1", "name").str()')
age = xy.eval('table.get("user1", "age").int()')
salary = xy.eval('table.get("user1", "salary").float()')
Helper Classes
Problem: Repetitive code for common operations.
Solution: Create helper classes:
class GrapaTableHelper:
def __init__(self, grapa_instance, table_name):
self.xy = grapa_instance
self.table_name = table_name
self.xy.eval(f'$global.{table_name} = {}.table("ROW")')
def mkfield(self, name, field_type, mode="VAR", size=None):
if size:
self.xy.eval(f'{self.table_name}.mkfield("{name}", "{field_type}", "{mode}", {size})')
else:
self.xy.eval(f'{self.table_name}.mkfield("{name}", "{field_type}")')
def set(self, key, value, field):
self.xy.eval(f'{self.table_name}.set("{key}", "{value}", "{field}")')
def get(self, key, field, convert_type="str"):
return self.xy.eval(f'{self.table_name}.get("{key}", "{field}").{convert_type}()')
Command Line Issues
File Execution
Problem: .grc files don't execute properly.
Solution: Use correct command line options:
# ✅ Correct: Use -f for .grc files
.\grapa.exe -f "examples/basic_example.grc"
# ❌ Incorrect: -c may cause parsing issues
.\grapa.exe -c "examples/basic_example.grc"
Quiet Mode
Problem: Too much output from version headers.
Solution: Use -q flag to suppress version output:
.\grapa.exe -f "examples/basic_example.grc" -q
Debug Output Stream Separation
Problem: Debug output mixed with normal program output.
Solution: Use stream redirection to separate outputs:
# Separate normal and debug output
.\grapa.exe -d -f "script.grc" > normal_output.txt 2> debug_output.txt
# Suppress debug output entirely
.\grapa.exe -d -f "script.grc" 2> $null
# Capture only debug output
.\grapa.exe -d -f "script.grc" > $null 2> debug_output.txt
Note: Grapa properly separates normal program output (stdout) from debug output (stderr), allowing for flexible stream redirection and logging. You can also write directly to these streams using $file().set($stdout, content) and $file().set($stderr, content).
Best Practices for Debugging
1. Test Incrementally
# Test each operation step by step
xy.eval('$global.test = "Hello"')
print("Step 1: Variable created")
result = xy.eval('test')
print(f"Step 2: Variable retrieved: {result}")
xy.eval('$global.fs = $file()')
print("Step 3: File object created")
2. Use Descriptive Variable Names
# ✅ Good: Clear variable names
xy.eval('$global.user_table = {}.table("ROW")')
xy.eval('$global.file_system = $file()')
# ❌ Bad: Unclear variable names
xy.eval('$global.t = {}.table("ROW")')
xy.eval('$global.f = $file()')
3. Parameter Side Effects
Problem: Function parameters are modified unexpectedly
# ✅ Fixed: Default values are now immutable
f = op(x=0) {
x += 1;
x;
};
f(); // Returns 1
f(); // Returns 1 (expected - default value is not modified):
# ❌ Problem: Original variables are modified
data = [1, 2, 3];
process = op(arr) {
arr[0] = 999;
arr;
};
process(data); // Returns [999, 2, 3]
data; // Now [999, 2, 3] (unexpected!)
Solution: Use the .copy() method or copy functions when you need to avoid side effects
// ✅ Solution 1: Use .copy() method (recommended)
data = [1, 2, 3];
process(data.copy()); // Returns [999, 2, 3]
data; // Still [1, 2, 3] (expected!)
// ✅ Solution 2: Copy function to avoid side effects
copy = op(x) { x; };
data = [1, 2, 3];
process(copy(data)); // Returns [999, 2, 3]
data; // Still [1, 2, 3] (expected!)
Why This Happens: Grapa uses pass-by-reference for performance reasons, avoiding the need for a full garbage collection system.
4. Check Return Values
# Always check what operations return
result = xy.eval('some_operation()')
print(f"Operation returned: {result}")
print(f"Type: {type(result)}")
4. Use Error Handling
try:
result = xy.eval('some_operation()')
if result == {"error":-1}:
print("Operation failed")
else:
print("Operation succeeded")
except Exception as e:
print(f"Exception occurred: {e}")
Common Patterns and Solutions
Table Operations Pattern
# ✅ Complete table operation pattern
xy.eval('$global.table = {}.table("ROW")')
xy.eval('table.mkfield("name", "STR", "VAR")')
xy.eval('table.mkfield("age", "INT")')
xy.eval('table.mkfield("salary", "FLOAT", "FIX", 8)')
xy.eval('table.set("user1", "John Doe", "name")')
xy.eval('table.set("user1", 30, "age")')
xy.eval('table.set("user1", 75000.50, "salary")')
name = xy.eval('table.get("user1", "name").str()')
age = xy.eval('table.get("user1", "age").int()')
salary = xy.eval('table.get("user1", "salary").float()')
File Operations Pattern
# ✅ Complete file operation pattern
xy.eval('$global.fs = $file()')
xy.eval('fs.set("test.txt", "Hello World")')
content = xy.eval('fs.get("test.txt").str()')
xy.eval('fs.rm("test.txt")')
This troubleshooting guide covers the most common issues and their solutions. When encountering problems, start with the namespace and type conversion issues, as these are the most frequent causes of {"error":-1} responses.
For Python Users: If you encounter issues with GrapaPy integration, see the Migration Tips for Python Users and GrapaPy Namespace Solution for solutions to common problems and best practices.