Skip to Content
RiusSDKTroubleshooting

Troubleshooting

Symptoms first, causes second. Everything here assumes a current SDK: glassflow-rius 1.1.1 or newer for Python, @glassflow-ai/rius 1.2.0 or newer for TypeScript. Older releases behave the same on the basics, but some log lines quoted below were worded differently, and some fixes noted below need these versions.

No traces are arriving

Check in this order:

  1. Is the SDK disabled? RIUS_DISABLED=1 (or true/yes/on) silently drops all spans in-process. Also check disabled=True in code.

  2. Is sampling set low? RIUS_SAMPLE_RATE=0.1 keeps one trace in ten; 0 keeps none. Sampling decides per whole trace, so a sampled-out trace is completely invisible, not partially.

  3. Did the process exit before the batch flushed? Batches flush every 5 seconds by default. Short scripts can exit between batches if the interpreter is killed rather than exiting cleanly; call client.flush() at the end. Serverless invocations should always flush explicitly. Since 0.9.0, flush() returning True confirms delivery, not just an empty queue: it returns False when the queue drained but the last export was rejected.

  4. Endpoint and key. Since 0.9.0 the SDK diagnoses these itself, as warnings on the rius.* loggers:

    • init() warns immediately when no API key is configured and the SDK would export to the managed platform.
    • A one-shot background connectivity check at init() warns when the endpoint rejects your key (HTTP 401/403, check RIUS_API_KEY) or cannot be reached at all (check RIUS_ENDPOINT).
    • The first failed export logs a warning saying traces are not being delivered; repeats log at DEBUG until an export succeeds, and recovery logs at INFO.

    If you see none of these, raise your log level; the SDK warns but never raises in your code.

  5. Billing or rate limits. The export failure names the HTTP status. 402 means billing blocks ingest: check Settings → Plan & usage. 429 means the workspace is over its plan’s ingest rate: lower the volume with sampling or move to a plan with a higher rate. Both drop spans rather than buffer them; see Retries and failure behavior.

  6. Configuration still under GLASSFLOW_* names? From 1.0.0 the Python SDK reads only the RIUS_* environment variables (the TypeScript SDK never read the old names). A GLASSFLOW_API_KEY or GLASSFLOW_ENDPOINT left in your environment is ignored, so the SDK exports without a key or to the default endpoint, and nothing arrives in your workspace. Rename them; see the configuration reference.

”init() called again” warning

The global OpenTelemetry provider is write-once. A second init() returns the existing client unchanged and logs this warning. If you genuinely need to reconfigure, call client.shutdown() first; if you need a parallel pipeline, use init(set_global=False).

An instrumentation is not producing spans

  • The extra (Python) or optional package (TypeScript) must be installed in the same environment (pip install "glassflow-rius[openai]", or npm install @arizeai/openinference-instrumentation-openai). A requested-but-missing integration logs a warning at init() time.
  • The instrumented library must be installed too. In Python a missing one logs a DependencyConflict, see init() logs a DependencyConflict.
  • Scoped clients (set_global=False, or setGlobal: false in TypeScript 1.8.0 or later) do not auto-instrument; pass instruments explicitly.
  • If another OpenTelemetry setup already instrumented the library, the SDK leaves it alone by design; its spans go wherever that setup exports.
  • TypeScript, CommonJS apps: require the traced package before init(). The SDK patches the build of a provider or MCP SDK your process actually uses, so CommonJS and pure-ESM applications both get spans. The one pattern it cannot repair is a CommonJS require of openai, @anthropic-ai/sdk, or @modelcontextprotocol/sdk that happens only after init(): those calls stay untraced even though await client.ready lists the integration. Move the require above init(), where applications naturally place it, or trace the affected calls with manual generations. The langchain and vercel-ai integrations do not patch the package and have no ordering rule.
  • TypeScript, pnpm app on a serverless or file-tracing host: pass instrumentModules. A deployment that ships only the files your code imports, such as a Vercel function built from a pnpm workspace, can leave out the links the SDK follows to load its optional peers. client.ready then omits openai or anthropic and no LLM spans arrive. Since 1.1.0, init() logs a warning when your package.json lists the OpenAI or Anthropic instrumentation package but the SDK cannot load it, pointing at instrumentModules. The warning is best effort: it reads the package.json in the working directory, and stays silent when that file is not there. Pass the modules you import yourself; see pnpm and serverless deployments.
  • TypeScript, Vercel AI SDK 5 or 6: client.ready does not list vercel-ai. That is expected since 1.2.0: those versions need nothing registered, and their spans arrive from calls with experimental_telemetry: { isEnabled: true }. See Vercel AI SDK.

init() logs a DependencyConflict

DependencyConflict: requested: "anthropic >= 0.84.0" but found: "None"

The extra is installed but the library it instruments is not. Extras carry the instrumentation only, so glassflow-rius[anthropic] does not install anthropic. Rius takes no dependency on provider SDKs on purpose: pinning them would let an observability library dictate the version your model calls run against.

Install the library alongside the extra, and that integration starts working on the next init():

pip install "glassflow-rius[anthropic]" anthropic

The message comes from OpenTelemetry’s instrumentation base class, so it names the version range the instrumentation supports and None for what it found. Nothing else breaks: tracing continues, and only the integration whose library is missing stays off. If you meant not to have that library, drop the extra as well, or list the ones you want with init(instruments=[...]) so the SDK never tries the others.

Content is missing from spans

  • capture_content=False (or RIUS_CAPTURE_CONTENT=false) strips prompt/response content at export while keeping metadata. See Privacy controls for exactly which attributes are covered.
  • A masking callable that raises or returns None drops the affected attribute entirely, by design (fail closed), with a warning log.

Long agent spans lose their model, tools, or usage

An auto-instrumented agent span that looks complete for the first few turns and then loses its model, request parameters, tool definitions, system prompt, token usage, or output has hit OpenTelemetry’s per-span attribute count limit. init() raises it to 4096, so check whether OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT or OTEL_ATTRIBUTE_COUNT_LIMIT is set in your environment to something lower: a value you set wins. See Span attribute limit.

Queries or alerts stopped matching after upgrading to 1.0.0

1.0.0 changed four things a saved search, dashboard filter, or alert can match on:

  • Span names. Unnamed TOOL, AGENT, RETRIEVER, LLM, and EMBEDDING spans are now named after their operation and target, such as execute_tool search_orders, instead of after the function. An alert filtered on Step (the span name) needs the new name, or pass name explicitly to keep the old one. See Span names and identity.
  • Request parameters. model_parameters keys land on their canonical gen_ai.request.* key, or under rius.request.* when the conventions do not define them. For example, response_format is now rius.request.response_format. See Request parameters.
  • Retrieval operation. RETRIEVER spans carry gen_ai.operation.name retrieval, so update filters on the old operation name.
  • JSON spacing (Python). JSON-valued attributes are written compact, {"type":"json_object"} rather than {"type": "json_object"}, so a text match on the old spacing stops matching.

Auto-instrumented spans also leave the SDK with the canonical GenAI keys in place of the llm.* keys the integration’s package writes, so query the canonical ones, for example gen_ai.usage.input_tokens rather than llm.token_count.prompt.

Token or cost totals look doubled

Upgrade to glassflow-rius 1.1.1 or @glassflow-ai/rius 1.2.0, which count a model call once when a wrapper such as LangChain, LiteLLM, LlamaIndex, or the Vercel AI SDK records it too. If totals still look doubled, your setup is one of the cases in Still counted twice, which says which layer to keep.

Values look truncated

Inputs, outputs, messages, tool results, and serialized objects are capped at 32 KB in both SDKs, with an explicit …(truncated) suffix. This is a fixed safety limit on attribute size: a multi-megabyte tool result would otherwise become a multi-megabyte span. The cap applies to the serialized text, so a large object is cut once it is rendered to JSON.

Spans are dropped under load

The in-memory queue holds 2048 spans by default; overflow is dropped with a warning. Raise OTEL_BSP_MAX_QUEUE_SIZE, or lower the volume with sampling. See Reliability for all batching knobs.

Next steps

Last updated on