Skip to content

fix(doctor,memory): guard apiKey.trim() against non-string SecretRef values#35665

Closed
Sid-Qin wants to merge 1 commit intoopenclaw:mainfrom
Sid-Qin:fix/doctor-secretref-trim-35444
Closed

fix(doctor,memory): guard apiKey.trim() against non-string SecretRef values#35665
Sid-Qin wants to merge 1 commit intoopenclaw:mainfrom
Sid-Qin:fix/doctor-secretref-trim-35444

Conversation

@Sid-Qin
Copy link
Copy Markdown
Contributor

@Sid-Qin Sid-Qin commented Mar 5, 2026

Summary

openclaw doctor crashes with TypeError: resolved?.remote?.apiKey?.trim is not a function when the configuration uses SecretRef values (environment variable references like $OPENAI_API_KEY or vault-resolved secrets) for API keys. The config resolver returns a SecretRef object instead of a plain string, and calling .trim() on it throws.

Two locations fixed:

  1. src/commands/doctor-memory-search.tshasRemoteApiKey check
  2. src/memory/embeddings-ollama.tsresolveOllamaApiKey function

Both now check typeof rawApiKey === "string" before calling .trim().

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature
  • Breaking change
  • Documentation update
  • Refactoring
  • Test update

Scope

  • Agents / Model integration
  • Channels / Plugins
  • CLI / TUI
  • Gateway
  • Security

Linked Issues

Closes #35444

User-Visible Changes

openclaw doctor no longer crashes when API keys are configured via environment variable references or vault secrets.

Security Impact

  1. Does this change handle user input? No — configuration values only
  2. Does this change affect authentication or authorization? No
  3. Does this change introduce new dependencies? No
  4. Does this change affect data storage or transmission? No
  5. Does this change modify security-sensitive code paths? No

Verification

  • 16 existing tests pass (14 doctor-memory-search + 2 embeddings-ollama)
  • Formatted with oxfmt

Evidence

 ✓ src/memory/embeddings-ollama.test.ts (2 tests) 6ms
 ✓ src/commands/doctor-memory-search.test.ts (14 tests) 5ms
 Test Files  2 passed (2)
      Tests  16 passed (16)

Human Verification

  • Configure openclaw.json with $OPENAI_API_KEY env reference for memory search API key
  • Run openclaw doctor — should complete without TypeError

Compatibility

Fully backward compatible. String API keys behave identically.

Failure Recovery

Revert this single commit to restore previous behavior.

Risks and Mitigations

Risk Mitigation
SecretRef objects treated as truthy when checking hasRemoteApiKey This is correct behavior — a SecretRef indicates a key was configured, even if not yet resolved to a string

…values

When openclaw.json uses environment variable references or vault-resolved
secrets for API keys, the config resolver returns a SecretRef object
instead of a plain string. Calling .trim() on this object throws
TypeError: resolved?.remote?.apiKey?.trim is not a function, crashing
`openclaw doctor` at the end of its run.

Added typeof checks before calling .trim() in doctor-memory-search.ts
and embeddings-ollama.ts.

Closes openclaw#35444

Made-with: Cursor
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 5, 2026

Greptile Summary

This PR fixes a real TypeError crash in openclaw doctor and Ollama embedding resolution by guarding .trim() calls against non-string SecretRef objects that the config resolver can return.

Changes verified:

  • src/commands/doctor-memory-search.ts (line 30): Adds typeof rawApiKey === "string" check before calling .trim(). A non-string SecretRef is still truthy, correctly indicating that a key was configured.
  • src/memory/embeddings-ollama.ts (lines 49-50): Same pattern—guards .trim() with a typeof check, gracefully falling back to provider-config and env-var sources when the value is a SecretRef.

Design rationale:
The inline typeof check diverges intentionally from the shared normalizeResolvedSecretInputString helper used by other remote embedding providers. This is appropriate because Ollama is a local, optional provider where silent fallback to env-vars is the correct behavior, whereas the shared helper would throw an error if a SecretRef were unresolved. The fix respects these semantic differences.

Test coverage:
All 16 pre-existing tests pass (14 doctor-memory-search + 2 embeddings-ollama). The fix is backward-compatible—string API keys behave identically.

Verdict: The fix is correct, minimal, and well-scoped to the reported issue.

Confidence Score: 4/5

  • Safe to merge—the fix directly addresses the reported crash without introducing new dependencies or behavioral changes for string-valued API keys.
  • The fix is correct, minimal, and directly addresses the reported TypeError crash. Both changes follow the same defensive pattern: check typeof rawApiKey === "string" before calling .trim(). All 16 pre-existing tests pass. The design choice to use inline typeof guards (rather than the shared helper) is intentional and appropriate for Ollama's semantics as a local optional provider. The only minor gap is the absence of a specific regression test for SecretRef-shaped values, but this is not critical given the simplicity and correctness of the fix.
  • No files require special attention

Last reviewed commit: 5a3ce5a

@joshavant
Copy link
Copy Markdown
Contributor

Thanks for the contribution here, and for helping narrow down the SecretRef doctor crash.

We merged #36835, which supersedes this PR and fixes the broader doctor/memory SecretRef surface in one place, including the related runtime embedding paths.

I’m closing this as superseded by #36835, but I appreciate the fix and the investigation that went into it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands Command implementations size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

openclaw doctor crashes with TypeError on SecretRef/vault-resolved apiKey values

2 participants