Skip to main content
Debugging Shed Skin programs involves understanding type inference errors, resolving compilation issues, and debugging the generated C++ code when necessary.

Common Compilation Errors

Type Inference Failures

Shed Skin must infer concrete types for all variables. When it can’t, you’ll see errors.

Error: “Variable has no type”

# Problem: Function never called
def calculate(x, y):
    return x + y

# Shed Skin doesn't know what types x and y are!
Solution: Call functions to establish types
def calculate(x, y):
    return x + y

if __name__ == '__main__':
    # Now Shed Skin knows: x and y are ints
    print(calculate(5, 10))
    # Or floats
    print(calculate(2.5, 3.7))
Always include a if __name__ == '__main__' block that exercises all code paths.

Error: “Incompatible types”

# Problem: Variable assigned different types
def process(use_float):
    if use_float:
        result = 3.14  # float
    else:
        result = "N/A"  # str - ERROR!
    return result
Solution: Keep types consistent
# Option 1: Use same type
def process(use_float):
    if use_float:
        result = 3.14
    else:
        result = 0.0  # Also float
    return result

# Option 2: Split into separate functions
def process_float(value):
    return value * 3.14

def process_string(text):
    return text.upper()

Error: “Cannot mix types in collection”

# Problem: Mixed-type list
data = [1, 2.5, "three"]  # ERROR!

# Problem: Mixed-type dict values
config = {
    'timeout': 30,      # int
    'host': 'localhost' # str - ERROR!
}
Solution: Use classes for heterogeneous data
class Config:
    def __init__(self):
        self.timeout = 30
        self.host = 'localhost'

config = Config()

Module Import Errors

Error: “Cannot locate module”

import mymodule  # ERROR: Can't find mymodule.py
Solutions:
1
Check File Location
2
Ensure the module is in the same directory or in a known location:
3
ls
# main.py
# mymodule.py  ← Must be present
4
Use -L Flag for Custom Paths
5
shedskin build -L /path/to/modules main
6
Check Module Structure
7
For packages, ensure __init__.py exists:
8
mypackage/
    __init__.py  ← Required
    module1.py
    module2.py

Error: “Unsupported module”

import pandas  # ERROR: Not supported by Shed Skin
Solution: Use supported modules only See Supported Modules for the list of supported modules. For unsupported modules:
  1. Create an extension module (using -e flag)
  2. Import it in pure Python code
  3. Use the unsupported library in the Python code
# fast_module.py - Compiled with Shed Skin
def compute_intensive_task(data):
    result = []
    for x in data:
        # Expensive computation
        result.append(x ** 2 + x * 3.14)
    return result

if __name__ == '__main__':
    compute_intensive_task([1.0, 2.0, 3.0])
# main.py - Pure Python with pandas
import pandas as pd
import fast_module  # Compiled extension

df = pd.read_csv('data.csv')
processed = fast_module.compute_intensive_task(df['values'].tolist())
df['processed'] = processed

None Type Errors

Error: “Cannot mix None with scalar type”

# Problem: None with int
x = 10
if something:
    x = None  # ERROR!

# Problem: Optional scalar parameter
def process(threshold=None):  # ERROR if called with int!
    pass
process(42)
Solution: Use sentinel values for scalars
# Use -1 or another sentinel
x = 10
if something:
    x = -1  # Valid sentinel

def process(threshold=-1):
    if threshold == -1:
        threshold = 100  # Default
    # ... use threshold

if __name__ == '__main__':
    process(42)
    process(-1)
None can only be mixed with objects, lists, and other non-scalar types.

Debugging Type Inference

Use Analyze Command

Check for errors without generating code:
shedskin analyze myprogram.py
This validates:
  • Type consistency
  • Module imports
  • Supported features

Generate Annotated Source

See what types Shed Skin inferred:
shedskin translate -a myprogram
This creates myprogram.ss.py with type annotations:
# Original
def calculate(x, y):
    result = x + y
    return result

# Annotated (myprogram.ss.py)
def calculate(x, y):  # x: int, y: int → int
    result = x + y    # result: int
    return result

Enable Debug Output

Get detailed type inference information:
shedskin translate -d 1 myprogram  # Level 1 debugging
shedskin translate -d 2 myprogram  # Level 2 (more verbose)

C++ Compilation Errors

Missing Dependencies

Error: “gc.h: No such file”

fatal error: gc.h: No such file or directory
Solution: Install Boehm GC development files
# Ubuntu/Debian
sudo apt-get install libgc-dev

# Fedora/RedHat
sudo dnf install gc-devel

# macOS
brew install bdw-gc

Error: “pcre2.h: No such file”

Solution: Install PCRE2 development files
# Ubuntu/Debian
sudo apt-get install libpcre2-dev

# Fedora/RedHat
sudo dnf install pcre2-devel

# macOS
brew install pcre2

Error: “Python.h: No such file”

Only for extension modules (-e flag):
# Ubuntu/Debian
sudo apt-get install python3-dev

# Fedora/RedHat
sudo dnf install python3-devel

Template/Syntax Errors

Sometimes the generated C++ has issues:
error: no matching function for call to 'max'
Causes:
  • Type inference created invalid type combination
  • Edge case in code generation
Solution: Simplify the problematic code
# Before: Complex expression
result = max([func(x) for x in data if x > 0], default=0)

# After: Break it down
valid_data = [x for x in data if x > 0]
processed = [func(x) for x in valid_data]
if processed:
    result = max(processed)
else:
    result = 0

Runtime Debugging

Segmentation Faults

Segfaults usually indicate:
  1. Null pointer dereference (accessing None)
  2. Invalid array access (especially with --nobounds)
  3. Stack overflow (deep recursion)
1
Reproduce with Python
2
First, verify the Python version works:
3
python myprogram.py
4
If Python crashes too, fix the Python code first.
5
Rebuild Without Optimizations
6
Remove safety-disabling flags:
7
# Don't use --nobounds or --nowrap
shedskin build myprogram
8
If it works now, the issue is bounds-related.
9
Use GDB
10
Debug the C++ binary:
11
shedskin translate myprogram
cd build/
g++ -g -O0 myprogram.cpp -o myprogram -lgc -lpcre2-8
gdb ./myprogram
12
In GDB:
13
(gdb) run
# Program crashes
(gdb) backtrace  # See where it crashed
(gdb) frame 0    # Inspect the crash location
(gdb) print variable_name  # Inspect variables
14
Add Debug Output
15
Insert print statements:
16
def process(data):
    print("Processing", len(data), "items")
    for i, item in enumerate(data):
        print(f"Item {i}: {item}")
        result = compute(item)
        print(f"Result: {result}")
    return result

Incorrect Results

If compiled code produces different output than Python:

Check Integer Overflow

# With default int32
x = 2_000_000_000
y = x * 2  # Overflow!

# Solution: Use --int64
shedskin build --int64 myprogram

Check Evaluation Order

Argument evaluation order differs between Python and C++.
# Problem: Depends on evaluation order
count = 0
def get_next():
    global count
    count += 1
    return count

print(get_next(), get_next())  # Order undefined!
Solution: Make order explicit
count = 0
def get_next():
    global count
    count += 1
    return count

a = get_next()
b = get_next()
print(a, b)  # Now deterministic

Check Float Precision

With -ffast-math, floating-point results may differ slightly:
# Exact IEEE floating-point
shedskin build myprogram

# Fast but less precise
echo "-O3 -ffast-math" > FLAGS
shedskin build myprogram

Memory Issues

Use Valgrind to detect memory problems:
shedskin build myprogram
valgrind --leak-check=full build/myprogram
For extension modules, disable GC first:
shedskin build -e --nogc mymodule
valgrind --leak-check=full python main.py

Extension Module Issues

Import Fails

>>> import mymodule
ImportError: libgc.so.1: cannot open shared object file
Solution: Check library path
# Find missing libraries
ldd build/mymodule.so

# Add to LD_LIBRARY_PATH
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
python
>>> import mymodule  # Should work now

Type Conversion Errors

>>> import mymodule
>>> mymodule.process("test")
Segmentation fault
Cause: Type mismatch between Python call and C++ expectation Solution: Check what types the function expects
# Generate annotated source
shedskin translate -a -e mymodule
cat mymodule.ss.py  # Check parameter types
Ensure Python calls match:
# If function expects list of ints
mymodule.process([1, 2, 3])  # Correct
mymodule.process("123")      # Wrong!

Global Variable Issues

# mymodule.py
COUNTER = 0

def increment():
    global COUNTER
    COUNTER += 1

def get_counter():
    return COUNTER
>>> import mymodule
>>> mymodule.increment()
>>> mymodule.COUNTER  # Still 0!
Cause: Globals are converted once at initialization Solution: Use getter functions
>>> mymodule.increment()
>>> mymodule.get_counter()  # Returns 1

Debugging Workflow

1
Verify Python Code
2
Ensure the Python version works correctly:
3
python myprogram.py
4
Check Compatibility
5
Run analysis:
6
shedskin analyze myprogram.py
7
Fix any errors reported.
8
Compile Without Optimizations
9
Build in debug mode:
10
shedskin build myprogram
11
Test the compiled version:
12
build/myprogram
13
Compare Outputs
14
Verify identical behavior:
15
python myprogram.py > python_output.txt
build/myprogram > cpp_output.txt
diff python_output.txt cpp_output.txt
16
Add Optimizations Gradually
17
Once it works, add optimizations:
18
# Add --nobounds
shedskin build --nobounds myprogram
build/myprogram  # Test

# Add --nowrap
shedskin build --nobounds --nowrap myprogram
build/myprogram  # Test
19
Profile and Optimize
20
See Optimization guide for performance tuning.

Common Workarounds

Block Comments for Incompatible Code

Exclude code from compilation:
print("Results:", results)

#{
import matplotlib.pyplot as plt
plt.plot(results)
plt.show()
#}
The visualization code runs in Python but is ignored by Shed Skin.

Separate Test Code

Use separate test files:
# mymodule.py - compilable
def compute(data):
    return [x * 2 for x in data]

if __name__ == '__main__':
    print(compute([1.0, 2.0, 3.0]))
# test_mymodule.py - Python only
import mymodule
import pytest

def test_compute():
    assert mymodule.compute([1, 2, 3]) == [2, 4, 6]

Type Assertion Comments

Add comments documenting expected types:
def process(data, threshold):
    # data: list[float]
    # threshold: float
    # returns: list[float]
    return [x for x in data if x > threshold]
While Shed Skin ignores these, they help you maintain type consistency.

Getting Help

If you encounter issues:
  1. Check documentation - Review restrictions
  2. Search examples - Look for similar code in /examples/
  3. Report bugs - File issues at https://github.com/shedskin/shedskin/issues
  4. Ask questions - Join the mailing list
When reporting bugs, include:
  • Your Shed Skin version (shedskin --version)
  • Minimal reproducible example
  • Full error message
  • Platform (OS, Python version)