Issue Origin
Observed or reproduced in a real environment
Bug Description
sync_session() in examples/skills/ov_dream/scripts/dream.py assumes every message's content field is a list[dict] of blocks. In real OpenClaw transcripts some messages store content as a plain string. Iterating a string yields single characters, and calling .get() on a character raises AttributeError, which aborts the entire sync so no session gets committed.
Measured distribution over 1609 messages from one real OpenClaw workspace:
| content type |
count |
| list |
1518 |
| str |
91 |
| blocks inside lists (all dict) |
2154 |
So roughly 5.7% of messages hit this path — on this machine it meant the skill could never complete a single sync until patched.
Steps to Reproduce
- Install the ov_dream skill from main branch into an OpenClaw workspace.
- Configure serverless mode (OPENVIKING_AUTH_MODE=serverless) with a valid API key.
- Ensure at least one session transcript contains a message whose
content is a plain string rather than a block list (this happens naturally in real usage).
- Run
python3 scripts/dream.py dream.
- The run aborts; no session is committed.
Expected Behavior
Messages with string content should be treated as plain text and synced normally. Sync should complete and commit all sessions.
Actual Behavior
The run aborts with AttributeError: 'str' object has no attribute 'get'. No session is committed, so the skill is completely non-functional on any workspace that contains at least one such message.
Minimal Reproducible Example
# any message shaped like this triggers it
msg = {"role": "user", "content": "plain string instead of block list"}
# dream.py, around line 289
blocks = msg.get("content", [])
text_parts = [
block.get("text", "").strip()
for block in blocks
if block.get("type") == "text"
]
# -> AttributeError: 'str' object has no attribute 'get'
Suggested fix (three defenses: handle str, coerce non-list to empty, require each block to be a dict):
blocks = message.get("content", [])
if isinstance(blocks, str):
content = blocks.strip()
else:
if not isinstance(blocks, list):
blocks = []
text_parts = [
block.get("text", "").strip()
for block in blocks
if isinstance(block, dict) and block.get("type") == "text"
]
content = "\n".join(part for part in text_parts if part)
After applying this locally, a full sync completed: 10 sessions, all committed=True, 522 messages, rc=0, 9m14s.
Error Logs
AttributeError: 'str' object has no attribute 'get'
Note on diagnosability: `main()` wraps everything in `except Exception: print(str(exc)); return 1`, which swallows the traceback. The user only sees that single line with no file or line number. I had to write a custom driver that does `import dream` and calls `sync_session()` directly with `traceback.print_exc()` in order to locate the failing line. Re-raising, or printing `traceback.format_exc()` behind a debug flag, would turn this into a 30-second fix.
OpenViking Version
examples/skills/ov_dream from main branch, fetched 2026-08-23 (raw.githubusercontent.com/volcengine/OpenViking/main/examples/skills/ov_dream/scripts/dream.py). The skill files carry no version string.
Python Version
3.12.3
Operating System
Linux
Model Backend
None
Additional Context
Environment: OpenClaw workspace, transcripts at ~/.openclaw/agents/main/sessions/*.jsonl, serverless auth mode against api.vikingdb.cn-beijing.volces.com.
Two unrelated minor observations while setting this up:
-
The setup instructions ask the user to supply OPENVIKING_AGENT_ID, but grep -c AGENT_ID scripts/dream.py returns 0 — the script never reads it. Removing it from the docs would avoid confusion (I nearly went asking for a value that turned out to be unused).
-
The docs suggest running the sync every 5 minutes. In practice each message costs one separate HTTP round-trip (measured 0.95-1.87s each), so a first full sync of 1609 messages takes roughly 27 minutes and a 5-minute schedule will pile up overlapping runs. Mentioning a mutex (e.g. flock -n) or a longer default interval in the docs would help. I settled on every 15 minutes with flock.
Issue Origin
Observed or reproduced in a real environment
Bug Description
sync_session()inexamples/skills/ov_dream/scripts/dream.pyassumes every message'scontentfield is alist[dict]of blocks. In real OpenClaw transcripts some messages storecontentas a plain string. Iterating a string yields single characters, and calling.get()on a character raises AttributeError, which aborts the entire sync so no session gets committed.Measured distribution over 1609 messages from one real OpenClaw workspace:
So roughly 5.7% of messages hit this path — on this machine it meant the skill could never complete a single sync until patched.
Steps to Reproduce
contentis a plain string rather than a block list (this happens naturally in real usage).python3 scripts/dream.py dream.Expected Behavior
Messages with string
contentshould be treated as plain text and synced normally. Sync should complete and commit all sessions.Actual Behavior
The run aborts with
AttributeError: 'str' object has no attribute 'get'. No session is committed, so the skill is completely non-functional on any workspace that contains at least one such message.Minimal Reproducible Example
Error Logs
OpenViking Version
examples/skills/ov_dream from main branch, fetched 2026-08-23 (raw.githubusercontent.com/volcengine/OpenViking/main/examples/skills/ov_dream/scripts/dream.py). The skill files carry no version string.
Python Version
3.12.3
Operating System
Linux
Model Backend
None
Additional Context
Environment: OpenClaw workspace, transcripts at ~/.openclaw/agents/main/sessions/*.jsonl, serverless auth mode against api.vikingdb.cn-beijing.volces.com.
Two unrelated minor observations while setting this up:
The setup instructions ask the user to supply
OPENVIKING_AGENT_ID, butgrep -c AGENT_ID scripts/dream.pyreturns 0 — the script never reads it. Removing it from the docs would avoid confusion (I nearly went asking for a value that turned out to be unused).The docs suggest running the sync every 5 minutes. In practice each message costs one separate HTTP round-trip (measured 0.95-1.87s each), so a first full sync of 1609 messages takes roughly 27 minutes and a 5-minute schedule will pile up overlapping runs. Mentioning a mutex (e.g.
flock -n) or a longer default interval in the docs would help. I settled on every 15 minutes with flock.