Troubleshooting
Symptom-first index for common Solwyn SDK problems in production
This page is a symptom-first index. Find the symptom you are seeing in your application or logs, then follow the resolution.
My calls are not appearing in the dashboard
The most common cause is the metadata reporter being shut down before its background batch flushes.
Resolution:
- Confirm
client.close()is called when your application exits, or that you used a context manager (with Solwyn(...) as client:/async with AsyncSolwyn(...) as client:). - Look for
reporter.ingest_events_rejectedwarnings (SDK v0.1.7+). If you see them, your batches are reaching Solwyn Cloud but specific events were refused — usually a model Solwyn cannot price yet. See the next section. - Look for the warning
Cloud API budget check failedin your logs. If you see it, the SDK could not reach Solwyn Cloud — check your network andSOLWYN_API_URLvalue. - Verify your
SOLWYN_API_KEYis associated with the project ID you are reporting under. The dashboard shows usage per project.
If using AsyncSolwyn, you must await client.close() (not client.close()).
reporter.ingest_events_rejected warnings in my logs
Solwyn Cloud accepted the metadata batch but refused to record specific events in it — this is not a connectivity failure, and the other events in the batch were recorded normally. Logged at WARNING level by the solwyn.reporter logger, one aggregated line per distinct rejection code and model per batch (SDK v0.1.7+):
reporter.ingest_events_rejected: code=unknown_model model=vendor-x-1 count=2 message=Solwyn does not have pricing for model 'vendor-x-1'. File an issue at https://github.com/solwyn-ai/solwyn-python-sdk/issues or contact support — we typically add new models within 24h.What the codes mean:
unknown_model— Solwyn has no pricing entry for that model identifier. Those events were dropped, so their cost is missing from the dashboard.unknown_service_tier— the event carried a service tier Solwyn Cloud does not recognize, so the cost could not be computed at the correct rate.- Rejection codes are server-owned and the set can grow without an SDK release; an unfamiliar code is logged the same way. The
messagefield carries the server's guidance verbatim.
Resolution:
- Rejected events are terminal: the SDK logs and drops them, never retries — resubmission would be rejected identically until a pricing entry lands server-side. The corresponding calls stay absent from the dashboard.
- For
unknown_model, open an issue at github.com/solwyn-ai/solwyn-python-sdk with themodel=value from the log line. Pricing lives server-side: once Solwyn adds the entry, subsequent traffic is priced automatically — no SDK upgrade or redeploy on your side. The already-rejected calls are not recovered retroactively. - For
unknown_service_tier, include the full log line in the issue — the server'smessagenames the tier it could not match, and support for it is likewise a server-side fix. - No action is needed for the accepted events in the same batch — they are already durable.
For the line-by-line format reference, see Logging.
ConfigurationError: Invalid API key format at construction
Your api_key did not match the required pattern sk_proj_<64 lowercase hex chars>.
Common causes:
- Trailing whitespace or newline (often from copy-paste). Strip with
os.environ["SOLWYN_API_KEY"].strip(). - Missing
sk_proj_prefix. - Using the dashboard's display name instead of the raw key.
- Quoting the value in your
.envfile with extra characters.
The error's field attribute is set to "api_key" and the message includes the first 12 characters of what the SDK saw.
Dashboard shows no costs and budget caps aren't enforcing
Your SOLWYN_API_KEY is a read-only key. Solwyn Cloud rejects every SDK write surface — budget checks, usage and metadata reporting, and breaker-state reports — from a read-only key with the same structured permission error. The SDK recognizes that response on its budget-check and reporting paths, and logs it once per process, at ERROR level:
solwyn.configuration_error.read_only_key: the configured API key is read-only; use a full-scope project key for SDK budget enforcement and metadata reportingAfter that one log line, the SDK suppresses the repeated generic Cloud-API warnings for the same cause and drops reporting for those requests. Budget checks follow your fail_open setting: on the default fail_open=True they fail open — your provider calls keep working, but enforcement and attribution do not; with fail_open=False the usual local fallback applies and calls can be denied. Detection is exact: only the structured read-only permission response triggers this path; other 401/403 responses surface as the ordinary Cloud API budget check failed warnings below, not this one.
Resolution:
- Search application logs (including startup, since this fires once per process) for the
solwyn.configuration_error.read_only_keyline above. - Swap in a full-scope project key. See API keys.
- Redeploy with the new key — budget enforcement and dashboard attribution resume on the next call.
Cloud API budget check failed warnings in my logs
Solwyn Cloud was unreachable for one budget check. This is logged at WARNING level by the solwyn logger.
When to ignore: Single occurrences during transient network issues. With the default fail_open=True, your LLM calls proceeded normally with local tracking.
When to investigate: Persistent failures — every call. Check:
SOLWYN_API_URLis correct (defaulthttps://api.solwyn.ai).- The host running your code can reach the API URL (
curl -I $SOLWYN_API_URL). - Your API key has not been revoked in the dashboard.
If you set fail_open=False, persistent failures will start denying calls once the local cache expires.
BudgetExceededError raised when I did not expect it
You configured budget_mode="hard_deny" and a call's pre-flight check returned "denied" from Solwyn Cloud.
Diagnose:
- Inspect
e.budget_limitande.current_usageon the exception. Ifcurrent_usageis at or nearbudget_limit, the budget genuinely is exhausted. - Check the dashboard for the project's current period spend.
- Confirm you are looking at the right project — multi-agent setups often have separate projects per agent.
To allow calls through while you investigate, switch to budget_mode="alert_only" temporarily.
My calls keep raising ProviderUnavailableError
The provider's circuit breaker is open and the SDK is refusing to send calls. Look for Circuit breaker opened due to failures in your logs.
Resolution:
- The circuit closes automatically after the recovery probe succeeds. With defaults, this is roughly 60 seconds (±20% jitter, so up to 72 seconds) + 2 successful probe calls.
- To recover faster, restart the process — circuit-breaker state is per-process and resets on restart.
- Investigate why the provider was failing — Solwyn does not catch provider exceptions, so the original errors should be visible in your logs from the calls that opened the circuit.
To require more failures before opening (less aggressive), increase circuit_breaker_failure_threshold. To recover faster, decrease circuit_breaker_recovery_timeout. A same-provider model fallback that fails on both the primary and the fallback model still records only one failure against that provider's breaker — failures are deduplicated per provider within a single request — so with the default threshold of 3, the circuit opens after three failed requests.
If you configure a fallback= chain, ProviderUnavailableError is only raised when every candidate is unavailable — a single provider being down should fail over rather than raise. If it raises with a fallback configured, check e.attempted to see which providers the router tried.
My dashboard shows failover usage I didn't expect
Some calls failed on the requested provider/model and were served by a fallback entry. The dashboard tags these events: is_model_fallback=true for a same-provider model swap, is_provider_fallback=true for a cross-provider hop, with failover_reason and requested_provider / requested_model describing what changed.
Resolution:
- Filter the dashboard by
is_model_fallback/is_provider_fallbackto see how often each kind of failover fires. - Inspect
failover_reason(circuit_open,primary_error,model_fallback) andfailover_error_classto understand why the primary was bypassed. - Check application logs for the original primary errors — the SDK surfaces them only when the whole chain is exhausted, so successful failovers won't reach your exception handlers.
- If failover fires more than expected, fix the underlying primary issue, or shorten the
fallback=chain to surface the original errors directly.
A cross-provider call raises UntranslatableRequestError
A failover hop to a different provider could not translate the request shape (for example an OpenAI response_format that has no Anthropic equivalent). The chain aborts before any network call, so no duplicate request is sent.
Resolution:
- Read
e.feature,e.source, ande.target— they name what could not be translated, structurally (never the value). - Either keep that call's request shape within what every provider in the chain can serve, or drop the cross-provider entry for calls that rely on a provider-specific feature.
UntranslatableModelErrormeans a fallback entry has no model set for its provider — add a concrete model to that tuple.
My async tests hang on shutdown
AsyncSolwyn started a background reporter task that was never closed.
Resolution:
Always use async with or call await client.close():
# Correct
async with AsyncSolwyn(AsyncOpenAI()) as client:
...
# Also correct
client = AsyncSolwyn(AsyncOpenAI())
try:
...
finally:
await client.close()
# Wrong — hangs on shutdown
client = AsyncSolwyn(AsyncOpenAI())
# ... no close()Streaming tokens are not being counted
The provider's stream did not emit usage data, or your code aborted the stream before the usage chunk arrived.
Resolution:
- For OpenAI: Solwyn injects
stream_options={"include_usage": True}automatically. If you pass your ownstream_optionsdict, Solwyn preserves your other keys and force-setsinclude_usage=True— even an explicitinclude_usage=Falseis overridden — so missing usage on a direct OpenAI stream is not caused bystream_options. - For OpenAI-compatible providers: Solwyn injects
include_usageonly where the provider documents support for it. It never injects for xAI, Mistral, Together, Fireworks, Perplexity, OpenRouter, or the genericopenai_compatiblecatch-all — those endpoints reject, deprecate, or simply do not document the parameter, and most deliver usage automatically in the final chunk. If no usage arrives at all, the SDK reports length-based estimated counts flaggedtoken_details.is_estimated=truewith a one-time WARNING — counts are present but approximate, not missing. See OpenAI-compatible providers. - For Anthropic and Google: usage events are emitted by default — no action needed.
- For Bedrock: usage arrives in the stream's terminal
metadataevent. Fully consumeresult["stream"], or on early abandonment callresult["stream"].close()(or usewith result["stream"]:) so the reservation settles with the observed usage. A stream that settles at zero tokens after real traffic logsBedrock stream settled at zero tokens— see Streaming. - For early aborts on the other providers: wrap the stream in
with stream:(sync) orasync with stream:(async) so Solwyn settles with the tokens it observed before the break. See Streaming.
The SDK is logging a lot — how do I quiet it?
All Solwyn log messages are emitted under the solwyn logger. Set its level to ERROR to silence WARNING-level messages:
import logging
logging.getLogger("solwyn").setLevel(logging.ERROR)For the full list of messages and what each one means, see Logging.
Still stuck?
- Check the SDK version with
from solwyn import __version__; print(__version__)and include it in any bug report. - Open an issue at github.com/solwyn-ai/solwyn-python-sdk with the version, the symptom, and any relevant log lines.