Errors
All Memproof exceptions inherit from MemproofError. Every exception carries three attributes:
code — a machine-readable error code string (e.g., "POLICY_DENIED").
message — a human-readable description of the error.
details — an optional dictionary with additional context.
from memproof import MemproofError, PolicyDeniedError, NotFoundError
Base Exception
MemproofError
The base class for all Memproof errors. You can catch this to handle any Memproof-specific exception.
class MemproofError(Exception):
def __init__(self, code: str, message: str, details: dict | None = None):
self.code = code
self.message = message
self.details = details
Machine-readable error code. Each subclass sets a fixed code value.
Human-readable error message.
Optional dictionary with structured error details (e.g., validation field errors, matched rule IDs).
Example
try:
result = await mp.remember(
content="sensitive data",
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
)
except MemproofError as e:
print(f"[{e.code}] {e.message}")
if e.details:
print(e.details)
Error Subclasses
ValidationError
Code: VALIDATION_ERROR
Raised when input data fails validation — for example, when a required field is missing, a field value is out of range, or the content string is empty.
class ValidationError(MemproofError):
def __init__(self, message: str, details: dict | None = None):
super().__init__("VALIDATION_ERROR", message, details)
Description of the validation failure.
details
dict | None
default:"None"
Optional dictionary with field-level error information. For example: {"field": "content", "error": "must be non-empty"}.
When raised:
- Content is empty or missing.
- Scope is missing required fields (
tenant_id, project_id, agent_id).
ttl_seconds is not a positive integer.
limit is outside the 1—100 range.
Example
from memproof import ValidationError
try:
result = await mp.remember(
content="", # empty content triggers validation error
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
)
except ValidationError as e:
print(e.message) # "Content must be non-empty"
NotFoundError
Code: NOT_FOUND
Raised when a requested resource does not exist.
class NotFoundError(MemproofError):
def __init__(self, message: str = "Not found"):
super().__init__("NOT_FOUND", message)
message
str
default:"\"Not found\""
Description of what was not found.
When raised:
get() is called with a memory_id that does not exist.
update() or forget() targets a non-existent memory.
get_operation_status() is called with an unknown operation_id.
Example
from memproof import NotFoundError
try:
record = await mp.get("non-existent-id")
except NotFoundError as e:
print(e.message) # "Not found"
ConflictError
Code: CONFLICT
Raised when an operation conflicts with the current state — typically an idempotency conflict or a concurrent modification.
class ConflictError(MemproofError):
def __init__(self, message: str = "Conflict", details: dict | None = None):
super().__init__("CONFLICT", message, details)
message
str
default:"\"Conflict\""
Description of the conflict.
details
dict | None
default:"None"
Optional details about the conflict (e.g., {"idempotency_key": "mp-abc", "existing_operation_id": "op-xyz"}).
When raised:
- An
idempotency_key is reused with different parameters than the original request.
- A concurrent modification is detected by the adapter.
Example
from memproof import ConflictError
try:
result = await mp.remember(
content="different content",
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
idempotency_key="already-used-key",
)
except ConflictError as e:
print(e.message)
print(e.details)
PolicyDeniedError
Code: POLICY_DENIED
Raised when the policy engine denies an operation based on the configured rules and risk assessment.
class PolicyDeniedError(MemproofError):
def __init__(self, message: str = "Operation denied by policy rule.", details: dict | None = None):
super().__init__("POLICY_DENIED", message, details)
message
str
default:"\"Operation denied by policy rule.\""
Explanation of the denial.
details
dict | None
default:"None"
May contain reason_codes, matched_rule_ids, and risk_assessment for debugging.
When raised:
- The policy engine evaluates the operation and returns a
deny action.
- A rule explicitly blocks the operation based on content, scope, risk level, or other criteria.
Example
from memproof import PolicyDeniedError
try:
result = await mp.remember(
content="store social security number 123-45-6789",
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
)
except PolicyDeniedError as e:
print(e.code) # "POLICY_DENIED"
print(e.message) # "Operation denied by policy rule."
print(e.details) # {"reason_codes": ["pii_detected"], ...}
QuarantinedError
Code: QUARANTINED
Raised when the policy engine quarantines an operation for offline review. The memory is not persisted until the quarantine is resolved.
class QuarantinedError(MemproofError):
def __init__(self, message: str = "Operation quarantined.", details: dict | None = None):
super().__init__("QUARANTINED", message, details)
message
str
default:"\"Operation quarantined.\""
Explanation of the quarantine.
details
dict | None
default:"None"
May contain the operation_id and reason_codes.
When raised:
- The policy engine returns a
quarantine action.
- The risk score or content triggers a quarantine rule in the policy configuration.
Example
from memproof import QuarantinedError
try:
result = await mp.remember(
content="potentially problematic content",
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
)
except QuarantinedError as e:
print(e.code) # "QUARANTINED"
print(e.details) # {"operation_id": "op-abc", ...}
ApprovalDeniedError
Code: APPROVAL_DENIED
Raised when a pending operation is explicitly denied by a human reviewer via the deny() method.
class ApprovalDeniedError(MemproofError):
def __init__(self, message: str = "Approval denied.", details: dict | None = None):
super().__init__("APPROVAL_DENIED", message, details)
message
str
default:"\"Approval denied.\""
Explanation of the denial.
details
dict | None
default:"None"
May contain the reviewer’s actor_id and notes.
When raised:
- A human reviewer calls
deny() on an operation that had a require_approval decision.
ProviderUnavailableError
Code: PROVIDER_UNAVAILABLE
Raised when the configured memory adapter backend is unreachable or returns an error.
class ProviderUnavailableError(MemproofError):
def __init__(self, message: str = "Provider unavailable"):
super().__init__("PROVIDER_UNAVAILABLE", message)
message
str
default:"\"Provider unavailable\""
Description of the provider failure.
When raised:
- The LangGraph checkpoint API is unreachable.
- The OpenAI Sessions API returns a server error.
- The MCP memory server connection times out.
- Any adapter backend fails to respond.
Example
from memproof import ProviderUnavailableError
try:
result = await mp.remember(
content="user preference",
scope={"tenant_id": "t1", "project_id": "p1", "agent_id": "a1"},
context={
"actor_type": "agent", "actor_id": "a1",
"source": "langgraph", "timestamp": "2026-01-15T10:30:00Z",
},
)
except ProviderUnavailableError as e:
print(e.message) # "Provider unavailable"
# Retry or fall back to a different adapter
InternalError
Code: INTERNAL_ERROR
Raised when an unexpected internal error occurs within the Memproof pipeline.
class InternalError(MemproofError):
def __init__(self, message: str = "Internal error"):
super().__init__("INTERNAL_ERROR", message)
message
str
default:"\"Internal error\""
Description of the internal error.
When raised:
- An unexpected exception occurs during orchestration that does not map to a more specific error type.
Error Handling Patterns
Catch-All
Catch MemproofError to handle any Memproof exception in a single block:
from memproof import MemproofError
try:
result = await mp.remember(content="hello", scope=scope, context=ctx)
except MemproofError as e:
log.error("Memproof error", code=e.code, message=e.message, details=e.details)
Granular Handling
Handle specific error types differently:
from memproof import (
PolicyDeniedError,
QuarantinedError,
NotFoundError,
ProviderUnavailableError,
MemproofError,
)
try:
result = await mp.remember(content="user data", scope=scope, context=ctx)
except PolicyDeniedError as e:
# Policy blocked the operation -- log and inform the caller
log.warning("Policy denied", reason_codes=e.details)
except QuarantinedError as e:
# Operation held for review -- track the operation_id
log.info("Quarantined", operation_id=e.details.get("operation_id"))
except ProviderUnavailableError:
# Backend is down -- retry with backoff
await retry_with_backoff(...)
except MemproofError as e:
# Any other Memproof error
log.error("Unexpected Memproof error", code=e.code, message=e.message)
Error Code Reference
| Error Class | Code | Default Message |
|---|
ValidationError | VALIDATION_ERROR | (varies — describes the validation failure) |
NotFoundError | NOT_FOUND | "Not found" |
ConflictError | CONFLICT | "Conflict" |
PolicyDeniedError | POLICY_DENIED | "Operation denied by policy rule." |
QuarantinedError | QUARANTINED | "Operation quarantined." |
ApprovalDeniedError | APPROVAL_DENIED | "Approval denied." |
ProviderUnavailableError | PROVIDER_UNAVAILABLE | "Provider unavailable" |
InternalError | INTERNAL_ERROR | "Internal error" |