Error Handling & Diagnostics¶
prik reports failures at several distinct stages. Understanding which stage failed helps you know where to look and what to fix.
Failure Stages¶
| Stage | Typical Cause | What to do |
|---|---|---|
| Parsing | Syntax prik cannot model, missing include | Check the diagnostic code and source location |
| Interface conversion | Unresolved types or missing interface details | Fix the source or edit the generated .pyi |
| Wrapper planning | Unsupported storage, layout, or callback combination | Read the full error message; it points to the declaration |
| Compilation / Linking | Compiler issues, missing modules/libraries | Run with --verbose to see native commands |
| Import | Missing library or incompatible build tools | Check paths and environment |
| Python Call | Wrong dtype, shape, layout, class, etc. | Match the generated contract |
| Native Execution | Application-level status, such as an error code | Convert it with @raises or handle it manually |
| Callback / Fatal | Exception in callback, stop, error stop |
Process usually aborts |
Verbose Output And Tracebacks¶
Use the two diagnostic flags for different problems:
| Flag | Use it when |
|---|---|
--verbose |
A build or link fails and you need the generated files, build steps, timings, or compiler commands. |
--debug |
prik fails unexpectedly and you need the full Python traceback. |
--verbose keeps the normal concise error message. --debug exposes prik's
internal call stack, so it is mainly useful when reporting or investigating an
prik bug.
Status Projection Example¶
You can turn Fortran status codes into Python exceptions using the @raises decorator in an edited contract.
Example:
subroutine solve(value, status, message)
integer(4), intent(in) :: value
integer(4), intent(out) :: status
character(len=32), intent(out) :: message
...
end subroutine
In your edited .pyi, project the hidden native outputs and then name those
projected results in @raises:
from prik.contracts import Addr, Arg, Int32, Return, String, native_call, raises
@raises(status="status", message="message", success=0)
@native_call([Addr(Arg(0)), Return("status", 0), Return("message", 1)])
def solve(value: Int32) -> tuple[Int32, String[32]]: ...
Then:
import numpy as np
try:
api.solve(np.int32(-1))
except RuntimeError as e:
print(e)
prik uses the projected status and message to determine the Python result: a
successful call returns None, while a non-success status raises
RuntimeError with the native message instead of returning either hidden
output.
For the complete status and message rules, see Translate Status Results into Exceptions.
Common Python Exceptions¶
TypeError— Wrong dtype, rank, shape, layout, class, or callbackValueError— Invalid options or contract valuesRuntimeError— Native status projected as exceptionImportError/OSError— Extension loading problems
Best Practices¶
- Always start with the full error message — it usually tells you exactly what went wrong.
- Use
--verbosewhen investigating build failures. - Use
--debugonly when an unexpected prik failure requires a Python traceback. - For complex contracts, generate the
.pyifirst and inspect it. - Run risky or untrusted callbacks in a subprocess if you need the main process to survive failures.
Next¶
- Finish with Building the Shared Library.