Handle Errors¶
flatline reports problems through two distinct mechanisms depending on when and where the error occurs. Understanding the difference helps you write robust error handling.
Two error channels¶
Exceptions (FlatlineError subclasses) are raised for hard errors detected
before or during decompilation setup — invalid arguments, unrecognized targets,
addresses outside the memory image, and decompiler engine failures.
DecompileResult.error is a structured ErrorItem value (not an exception)
returned inside the result object for non-fatal or partial failures that still
produce a result object. If result.error is not None, inspect its category
and message fields.
In the normal success case, no exception is raised and result.error is None.
The error hierarchy¶
All flatline exceptions inherit from FlatlineError. There are six concrete
subclasses, each with a stable category string:
FlatlineError
InvalidArgumentError category = "invalid_argument"
UnsupportedTargetError category = "unsupported_target"
InvalidAddressError category = "invalid_address"
DecompileFailedError category = "decompile_failed"
ConfigurationError category = "configuration_error"
InternalError category = "internal_error"
Catching specific errors¶
Import the exceptions you need and catch them individually for precise handling.
from flatline import (
DecompilerSession,
DecompileRequest,
InvalidArgumentError,
UnsupportedTargetError,
InvalidAddressError,
DecompileFailedError,
ConfigurationError,
InternalError,
FlatlineError,
)
request = DecompileRequest(
memory_image=b"\x55\x48\x89\xe5\xb8\x01\x00\x00\x00\x5d\xc3",
base_address=0x1000,
function_address=0x1000,
language_id="x86:LE:64:default",
compiler_spec="gcc",
)
try:
with DecompilerSession() as session:
result = session.decompile_function(request)
except InvalidArgumentError as e:
# Bad request construction: empty memory_image, wrong type, etc.
print(f"Bad argument: {e.message}")
except UnsupportedTargetError as e:
# language_id or compiler_spec not recognized.
# Call list_language_compilers() to find valid values.
print(f"Unknown target: {e.message}")
except InvalidAddressError as e:
# function_address is outside the supplied memory_image.
print(f"Address out of range: {e.message}")
except DecompileFailedError as e:
# The decompiler engine failed internally.
print(f"Decompilation failed: {e.message}")
except ConfigurationError as e:
# Installation or runtime data problem — see below.
print(f"Configuration problem: {e.message}")
except InternalError as e:
# flatline bug — see below.
raise
Catching all flatline errors¶
When you want a single fallback handler for any flatline problem, catch the base
class. The category attribute identifies which kind of error occurred.
from flatline import FlatlineError
try:
result = flatline.decompile_function(request)
except FlatlineError as e:
print(f"[{e.category}] {e.message}")
Per-category handling patterns¶
invalid_argument¶
Raised when the DecompileRequest or session arguments are malformed: empty
memory_image, non-string language_id, invalid analysis_budget fields, or
calling methods on a closed session.
from flatline import DecompileRequest, InvalidArgumentError
try:
# Empty memory_image — caught at construction time.
request = DecompileRequest(
memory_image=b"",
base_address=0x1000,
function_address=0x1000,
language_id="x86:LE:64:default",
)
except InvalidArgumentError as e:
print(e.message) # "memory_image must not be empty"
unsupported_target¶
Raised when language_id or compiler_spec is not found in the runtime data.
Enumerate available targets first.
import flatline
from flatline import UnsupportedTargetError
pairs = flatline.list_language_compilers()
valid_ids = {p.language_id for p in pairs}
if "x86:LE:64:default" not in valid_ids:
print("Target not available in this runtime data directory.")
invalid_address¶
Raised when function_address does not fall within the range
[base_address, base_address + len(memory_image)).
from flatline import DecompilerSession, DecompileRequest, InvalidAddressError
request = DecompileRequest(
memory_image=b"\x55\x48\x89\xe5\xc3",
base_address=0x1000,
function_address=0x9000, # Outside the image.
language_id="x86:LE:64:default",
)
try:
with DecompilerSession() as session:
result = session.decompile_function(request)
except InvalidAddressError as e:
print(f"Address 0x9000 is not mapped: {e.message}")
decompile_failed¶
Raised when the Ghidra decompiler engine itself encounters an unrecoverable
internal failure. This is distinct from partial or degraded output (which is
reported via result.error or result.warnings instead).
configuration_error and internal_error¶
configuration_error vs internal_error
These two categories have different remediation paths:
-
configuration_errormeans the problem is user-fixable. Common causes include a missing or corrupt runtime data directory, an incompatibleghidra-sleighinstallation, or a misconfiguredruntime_data_dirpath. Check your installation and the path you passed toDecompilerSession. -
internal_errormeans flatline itself has a bug. You should not need to handle this in normal operation. If you encounter one, please report it as a bug.
from flatline import ConfigurationError, InternalError
try:
with DecompilerSession(runtime_data_dir="/bad/path") as session:
result = session.decompile_function(request)
except ConfigurationError as e:
# Guide the user to fix their setup.
print(f"Setup problem (user-fixable): {e.message}")
print("Check that ghidra-sleigh is installed and runtime_data_dir is correct.")
except InternalError as e:
# Re-raise so it surfaces as an unhandled exception.
# Do not silently swallow internal errors.
raise
DecompileResult.error — inline error reporting¶
Some failures produce a result object rather than raising an exception. In these
cases result.error is an ErrorItem with three fields:
category— one of the six error category stringsmessage— human-readable descriptionretryable—Trueif the operation might succeed on a subsequent attempt
Check result.error after every call if you need to distinguish success from
degraded or failed output.
import flatline
result = flatline.decompile_function(request)
if result.error is not None:
print(f"Error [{result.error.category}]: {result.error.message}")
if result.error.retryable:
print("This error may be transient — retrying could help.")
else:
print(result.c_code)
# Warnings are separate from errors and can accompany a successful result.
for warning in result.warnings:
print(f"Warning [{warning.phase}]: {warning.message}")
Exceptions vs result errors
Exceptions are raised for problems detected before decompilation begins
(bad arguments, unknown targets, unmapped addresses) or for catastrophic
engine failures. DecompileResult.error is used when the decompiler
produces a result object but that result reflects a failure or partial
output. Always check both when robustness matters.