CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-py-solc

Python wrapper around the solc Solidity compiler

Pending
Overview
Eval results
Files

exceptions.mddocs/

Exception Handling

Comprehensive error handling for compilation failures and system issues. The py-solc library provides structured exceptions that give detailed information about what went wrong during compilation or installation.

Exception Classes

SolcError

Base exception class for all solc-related errors.

class SolcError(Exception):
    """
    Base exception for solc compilation errors.
    
    Attributes:
        command (list): Command that failed
        return_code (int): Process return code
        stdin_data (str): Input data sent to process (or None)
        stdout_data (str): Process stdout output (or None)
        stderr_data (str): Process stderr output (or None)
        message (str): Error message
    """
    
    def __init__(self, command, return_code, stdin_data, stdout_data, stderr_data, message=None):
        """
        Initialize SolcError with process information.
        
        Args:
            command (list): The solc command that was executed
            return_code (int): Process exit code
            stdin_data: Data sent to stdin (converted to string)
            stdout_data: Process stdout (converted to string)
            stderr_data: Process stderr (converted to string)
            message (str): Custom error message (optional)
        """

ContractsNotFound

Specific exception raised when no contracts are found during compilation.

class ContractsNotFound(SolcError):
    """
    Raised when no contracts are found during compilation.
    
    This exception inherits all attributes from SolcError.
    Default message: "No contracts found during compilation"
    """

Usage Examples

Basic Exception Handling

from solc import compile_source, SolcError

try:
    result = compile_source('''
        pragma solidity ^0.4.24;
        contract BrokenContract {
            // Syntax error: missing semicolon
            uint256 value = 42
        }
    ''')
except SolcError as e:
    print(f"Compilation failed: {e}")
    print(f"Command: {' '.join(e.command)}")
    print(f"Return code: {e.return_code}")
    if e.stderr_data:
        print(f"Error output: {e.stderr_data}")

Handling ContractsNotFound

from solc import compile_source, ContractsNotFound

try:
    # Source with no contracts (just comments)
    result = compile_source('''
        pragma solidity ^0.4.24;
        // This file contains no contracts
    ''')
except ContractsNotFound as e:
    print("No contracts found in the source code")
    print(f"Source code processed: {e.stdin_data[:100]}...")
    
    # Allow empty compilation instead
    result = compile_source('''
        pragma solidity ^0.4.24;
        // This file contains no contracts
    ''', allow_empty=True)
    print(f"Empty compilation result: {result}")

Specific Error Handling by Type

from solc import compile_standard, SolcError, ContractsNotFound

def safe_compile(source_code):
    try:
        return compile_standard({
            'language': 'Solidity',
            'sources': {
                'contract.sol': {'content': source_code}
            },
            'settings': {
                'outputSelection': {
                    '*': {'*': ['abi', 'evm.bytecode']}
                }
            }
        })
    except ContractsNotFound as e:
        print("Warning: No contracts found in source")
        return None
    except SolcError as e:
        if e.return_code == 1:
            print("Compilation error (syntax/semantic issues)")
        elif e.return_code == 2:
            print("Solc internal error")
        else:
            print(f"Unknown solc error (code {e.return_code})")
        
        # Try to extract detailed error information
        if e.stdout_data:
            try:
                import json
                output = json.loads(e.stdout_data)
                if 'errors' in output:
                    for error in output['errors']:
                        print(f"  {error.get('severity', 'error')}: {error.get('message', 'Unknown error')}")
            except (json.JSONDecodeError, KeyError):
                print(f"Raw error output: {e.stderr_data}")
        
        return None

Installation Error Handling

from solc import install_solc

def safe_install(version, platform=None):
    try:
        install_solc(version, platform=platform)
        print(f"Successfully installed solc {version}")
    except ValueError as e:
        print(f"Invalid version or platform: {e}")
    except OSError as e:
        print(f"System error during installation: {e}")
        # Check common issues
        if "git" in str(e).lower():
            print("Make sure git is installed and available in PATH")
        elif "permission" in str(e).lower():
            print("Permission denied - check write access to ~/.py-solc/")
        elif "network" in str(e).lower() or "download" in str(e).lower():
            print("Network error - check internet connection")
    except Exception as e:
        print(f"Unexpected error: {e}")
        print("Please check system requirements and try again")

Comprehensive Error Analysis

from solc import compile_source, SolcError, ContractsNotFound

def analyze_compilation_error(source_code):
    try:
        result = compile_source(source_code)
        return result
    except ContractsNotFound as e:
        return {
            'success': False,
            'error_type': 'no_contracts',
            'message': 'No contracts found in source code',
            'suggestion': 'Make sure your source code defines at least one contract'
        }
    except SolcError as e:
        error_info = {
            'success': False,
            'error_type': 'compilation_error',
            'return_code': e.return_code,
            'command': e.command,
            'message': str(e)
        }
        
        # Analyze stderr for common issues
        if e.stderr_data:
            stderr_lower = e.stderr_data.lower()
            if 'parsererror' in stderr_lower:
                error_info['category'] = 'syntax_error'
                error_info['suggestion'] = 'Check for syntax errors like missing semicolons, brackets, etc.'
            elif 'typeerror' in stderr_lower:
                error_info['category'] = 'type_error'
                error_info['suggestion'] = 'Check variable types and function signatures'
            elif 'declarationerror' in stderr_lower:
                error_info['category'] = 'declaration_error'
                error_info['suggestion'] = 'Check for undeclared variables or duplicate declarations'
            elif 'not found' in stderr_lower:
                error_info['category'] = 'import_error'
                error_info['suggestion'] = 'Check file paths and import statements'
            else:
                error_info['category'] = 'unknown_compilation_error'
                error_info['suggestion'] = 'Review the full error message for details'
        
        return error_info

# Usage
result = analyze_compilation_error('''
    pragma solidity ^0.4.24;
    contract Test {
        uint256 value = ; // Syntax error
    }
''')

if not result['success']:
    print(f"Error: {result['message']}")
    print(f"Suggestion: {result['suggestion']}")

Exception Information Access

from solc import compile_source, SolcError

try:
    compile_source("invalid solidity code")
except SolcError as e:
    print("Exception Details:")
    print(f"  Message: {e.message}")
    print(f"  Command: {' '.join(e.command) if e.command else 'None'}")
    print(f"  Return Code: {e.return_code}")
    print(f"  Has stdin data: {e.stdin_data is not None}")
    print(f"  Has stdout data: {e.stdout_data is not None}")
    print(f"  Has stderr data: {e.stderr_data is not None}")
    
    if e.stdin_data:
        print(f"  Input (first 100 chars): {e.stdin_data[:100]}...")
    
    if e.stdout_data:
        print(f"  Stdout (first 200 chars): {e.stdout_data[:200]}...")
    
    if e.stderr_data:
        print(f"  Stderr: {e.stderr_data}")

Error Categories

Compilation Errors (SolcError)

These occur when solc itself fails to compile the Solidity code:

  • Syntax Errors: Missing semicolons, unmatched brackets, etc.
  • Type Errors: Incorrect variable types, invalid casts, etc.
  • Declaration Errors: Undeclared variables, duplicate names, etc.
  • Import Errors: Missing files, circular imports, etc.
  • Version Errors: Pragma version mismatches, unsupported features

Contract Discovery Errors (ContractsNotFound)

These occur when compilation succeeds but no contracts are found:

  • Empty source files
  • Files with only comments
  • Files with only imports or libraries
  • Source files with syntax that prevents contract detection

System Errors (OSError, ValueError)

These occur due to system-level issues:

  • Installation Errors: Network issues, permission problems, missing dependencies
  • Binary Errors: Corrupted solc binary, wrong architecture
  • File System Errors: Permission denied, disk full, invalid paths

Best Practices

1. Always Handle Specific Exceptions

try:
    result = compile_source(source)
except ContractsNotFound:
    # Handle specifically
    pass
except SolcError:
    # Handle compilation errors
    pass
except Exception:
    # Handle unexpected errors
    pass

2. Provide Meaningful Error Messages

try:
    result = compile_source(source)
except SolcError as e:
    user_message = f"Failed to compile Solidity code: {e.message}"
    if "ParserError" in str(e):
        user_message += "\nPlease check your syntax for missing semicolons or brackets."
    raise RuntimeError(user_message) from e

3. Log Detailed Information for Debugging

import logging

try:
    result = compile_source(source)
except SolcError as e:
    logging.error(f"Solc compilation failed:")
    logging.error(f"  Command: {' '.join(e.command)}")
    logging.error(f"  Return code: {e.return_code}")
    logging.error(f"  Stderr: {e.stderr_data}")
    raise

4. Graceful Degradation

def try_compile_with_fallback(source):
    try:
        return compile_source(source)
    except ContractsNotFound:
        # Try with allow_empty
        return compile_source(source, allow_empty=True)
    except SolcError as e:
        if "version" in str(e).lower():
            # Try without pragma version
            source_no_pragma = re.sub(r'pragma solidity[^;]*;', '', source)
            return compile_source(source_no_pragma)
        raise

Install with Tessl CLI

npx tessl i tessl/pypi-py-solc

docs

exceptions.md

index.md

installation.md

legacy-compilation.md

standard-json-compilation.md

tile.json