How to Troubleshoot OpenMed Errors: A Complete Guide to Debugging the REST API and Core Library
OpenMed uses a unified JSON error envelope and structured exception handlers in openmed/service/app.py to surface validation, timeout, and runtime failures, while the core library propagates standard Python exceptions that you can debug by setting OPENMED_LOG_LEVEL=DEBUG and inspecting server logs.
OpenMed, developed by maziyarpanahi/openmed, separates concerns between a FastAPI REST service and a core NLP library. When you need to troubleshoot OpenMed errors, understanding this architecture is crucial because error handling differs between the HTTP layer—which returns structured JSON envelopes—and the Python API—which raises native exceptions.
Understanding OpenMed's Error Architecture
The REST Service Layer
The FastAPI service in openmed/service/app.py implements custom exception handlers that catch specific failure types and return a stable JSON envelope shaped as { "error": { "code": "...", "message": "...", "details": {...} } }.
The handlers include:
- RequestValidationError: Triggered by FastAPI/Pydantic input validation failures (HTTP 422). Returns detailed field-level error information.
- ServiceTimeoutError: Triggered when inference exceeds
OpenMedConfig.timeout(HTTP 504). Includes the timeout duration in the details. - ValueError: Catches invalid arguments from the core library (HTTP 400). Surfaces configuration mistakes like unsupported device names.
- StarletteHTTPException: Handles explicit HTTP errors such as 404 Not Found.
- Exception (fallback): Catches unhandled exceptions (HTTP 500) and returns a generic "Internal server error" message while logging the full traceback server-side.
All handlers funnel through the _error_response() helper function to ensure consistent formatting.
The Core Library Layer
The core library rarely uses custom exception types. Instead, it propagates standard Python exceptions:
openmed/core/models.py: RaisesExceptionfor model loading failures (missing files, architecture mismatches).openmed/core/config.py: RaisesValueErrorfor invalid configuration values (e.g.,DEVICE=CUDAinstead ofcuda).openmed/processing/batch.py: Wraps batch processing errors as genericException.openmed/ner/*: PropagatesExceptionfor missing label maps.openmed/mlx/*: RaisesExceptionfor MLX backend issues (missing native libraries).
Because the core bubbles up native exceptions, the REST service catches these and maps them to HTTP status codes.
Interpreting HTTP Error Codes and Responses
When troubleshooting the REST API, look for these specific patterns:
422 Validation Error
Occurs when the JSON payload fails Pydantic validation. Check the details array for specific field errors. Verify your request against the AnalyzeRequest or PIIExtractRequest schemas exposed in openmed/service/app.py.
504 Timeout
Indicates the request exceeded the OpenMedConfig.timeout value. The response includes timeout_seconds in the error details. Increase the timeout via export OPENMED_TIMEOUT=30 or optimize your model selection.
400 Bad Request
Typically surfaces as a ValueError from the core. Common causes include requesting a model name not found in openmed/core/model_registry.py or misconfiguring the device parameter.
500 Internal Server Error
The fallback handler for unhandled exceptions. This indicates an unexpected bug in model loading (openmed/core/models.py) or backend libraries (torch, transformers, mlx). Enable debug logging to capture the full traceback.
Step-by-Step Debugging Workflow
Follow this systematic approach to isolate and resolve failures:
-
Inspect the HTTP response body. The JSON envelope contains the error code and message. Parse the
error.detailsobject for specific field validation failures or timeout durations. -
Enable detailed logging. Set the environment variable before starting the service:
export OPENMED_LOG_LEVEL=DEBUG uv run uvicorn openmed.service.app:app --host 0.0.0.0 --port 8000The logger configuration in
openmed/utils/logging.pycontrols verbosity levels. -
Validate the runtime configuration. Instantiate
OpenMedConfigto verify environment variables:from openmed.core.config import OpenMedConfig cfg = OpenMedConfig.from_env() print(cfg) # Verify device, cache_dir, timeout valuesMis-typed values (e.g.,
DEVICE=GPUinstead ofcuda) raiseValueErrorbefore model loading begins. -
Confirm model availability. Check the model registry to ensure the requested model exists:
from openmed.core.model_registry import ModelRegistry registry = ModelRegistry() print(registry.list_available_models())Alternatively, use
runtime.loaded_models()to see which models are currently in memory. -
Reproduce locally with the Python API. Bypass the REST layer to see raw stack traces:
from openmed import analyze_text try: analyze_text("Patient has hypertension.", model_name="nonexistent_model") except Exception: import traceback traceback.print_exc() -
Clear the service runtime. If suspecting a stale state, clear the cache directory (
~/.cache/openmed) or restart the process to forceServiceRuntimereinitialization via_get_service_runtime()inopenmed/service/app.py.
Common Error Patterns and Solutions
Symptom: 422 Validation Error with field-level details
Root cause: Missing required fields or type mismatches in the JSON payload.
Solution: Validate your request against the OpenAPI schema at /openapi.json or the Pydantic models (AnalyzeRequest, PIIExtractRequest) defined in the service layer.
Symptom: 504 Timeout with "Request exceeded configured timeout"
Root cause: Model inference exceeds the default OpenMedConfig.timeout.
Solution: Increase the timeout environment variable (export OPENMED_TIMEOUT=60) or switch to a lighter model backbone.
Symptom: 400 Bad Request with "Model ... not found"
Root cause: The model name is not registered in openmed/core/model_registry.py or not pre-loaded.
Solution: Verify the model name against the registry or preload models via runtime.preload_models() before making requests.
Symptom: 500 Internal Server Error with "Internal server error"
Root cause: Missing dependencies (torch, transformers, mlx) or corrupt model files in openmed/core/models.py.
Solution: Enable DEBUG logging to identify the missing library, then reinstall with the correct extras per docs/getting-started.md.
Symptom: Empty response or hanging request
Root cause: Silent process death, often a segmentation fault in native MLX backend code.
Solution: Ensure platform compatibility (Apple Silicon for MLX, Linux for Torch) and check OS-level logs for segfaults.
Debugging with the Python API vs. REST Endpoint
When using the Python API directly, exceptions propagate without the JSON envelope, providing immediate stack traces:
from openmed import analyze_text
from openmed.core.config import OpenMedConfig
from openmed.core.model_loader import ModelLoader
cfg = OpenMedConfig.from_env()
loader = ModelLoader(config=cfg)
try:
result = analyze_text(
"Patient has hypertension.",
model_name="disease_detection_superclinical",
config=cfg,
loader=loader,
output_format="dict",
)
except Exception:
import traceback
traceback.print_exc()
When consuming the REST API, always check for the error envelope before processing the response:
import requests
resp = requests.post(
"http://localhost:8000/analyze",
json={"text": "test", "model_name": "unknown"},
)
payload = resp.json()
if "error" in payload:
print(f"Error code: {payload['error']['code']}")
print(f"Message: {payload['error']['message']}")
if payload["error"].get("details"):
print(f"Details: {payload['error']['details']}")
else:
print("Success:", payload)
Summary
- OpenMed errors follow a unified JSON envelope structure (
{ "error": { "code", "message", "details" } }) generated by handlers inopenmed/service/app.py. - The REST service maps specific exceptions to HTTP status codes: 422 for validation, 504 for timeouts, 400 for value errors, and 500 for unhandled exceptions.
- The core library raises standard Python exceptions (
ValueError,Exception) rather than custom types, making server logs essential for diagnosing 500 errors. - Enable debug logging by setting
OPENMED_LOG_LEVEL=DEBUGto capture full stack traces fromopenmed/core/models.pyand processing modules. - Validate configurations using
OpenMedConfig.from_env()and model names againstopenmed/core/model_registry.pybefore runtime. - For complex failures, reproduce the issue locally using the Python API to bypass the HTTP abstraction and see raw tracebacks.
Frequently Asked Questions
How do I enable debug logging in OpenMed?
Set the OPENMED_LOG_LEVEL environment variable to DEBUG before starting the server. The logging configuration in openmed/utils/logging.py reads this variable and increases verbosity, writing detailed stack traces to stdout. Use export OPENMED_LOG_LEVEL=DEBUG in bash or set it in your Docker environment.
What does a 422 validation error mean in OpenMed?
A 422 error indicates that your JSON payload failed FastAPI/Pydantic validation. This typically occurs when required fields are missing or data types are incorrect (e.g., passing a string where an integer is expected). Check the error.details array in the response for specific field-level messages, and validate your request against the AnalyzeRequest schema in openmed/service/app.py.
Why am I getting a 500 internal error when loading models?
HTTP 500 errors during model loading usually stem from missing dependencies or corrupt model files in openmed/core/models.py. The core library raises a standard Exception that the service catches and returns as a 500. Enable DEBUG logging to see the underlying traceback, then verify that you installed the required extras (e.g., pip install openmed[mlx] or openmed[torch]) as specified in docs/getting-started.md.
How can I check which models are loaded in OpenMed?
You can inspect the currently loaded models by accessing the ServiceRuntime via the _get_service_runtime() function in openmed/service/app.py, or by calling runtime.loaded_models() if you have a runtime instance. For a list of available models (not necessarily loaded), query the ModelRegistry class in openmed/core/model_registry.py using list_available_models().
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →