#Runtime issues: OpenAI fallback, EISDIR error, and SKILL.md size handling

1 messages · Page 1 of 1 (latest)

floral roost
#

I have a distributed OpenClaw setup running successfully:

LLM via Ollama (remote, qwen2.5:7b)
Memory working locally with embeddings (node-llama-cpp)
Agent + tool calling functional
Docker + network stable

Current architecture follows a clear separation (Agent / Tools / LLM / DB)

However, I’m now hitting several runtime issues:

Unexpected OpenAI fallback
Error: No API key found for provider "openai"
Occurs during model/slug resolution
Expected: strict usage of configured Ollama model
EISDIR error
EISDIR: illegal operation on a directory
Likely caused by agent using file read on directories
Skills not loading
Skipping skill due to oversized SKILL.md
Seems like size limit is incorrectly set or enforced

Config (relevant):

Model: ollama/qwen2.5:7b
Memory: local embeddings
Ollama: remote node
Node.js: v24
OpenClaw version: (please insert openclaw --version)

Questions:

How to disable OpenAI fallback completely (hard fail instead)?
Is the EISDIR issue expected agent behavior or missing guardrails?
How is SKILL.md size limit configured?

livid plinthBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> âś… Mark Solution

worn flumeBOT
wintry mist
#

krill is still typing

cunning mossBOT
#

First, please paste openclaw --version from the affected host. This is version-sensitive.

What I can confirm from current docs/code:

1. Disable OpenAI fallback completely

  • You can disable the configured model fallback chain with:
{
  agents: {
    defaults: {
      model: {
        primary: "ollama/qwen2.5:7b",
        fallbacks: [],
      },
    },
  },
#
}
  • But I do not see a global “strict hard-fail on model resolution” switch right now.
  • Current resolver behavior is still “if model ref cannot be resolved, fall back”, and the built-in default provider is openai.

So if you see No API key found for provider "openai", likely one of these is happening:

  • the actual model ref failed to resolve cleanly
  • a per-agent or session override is still set
  • models.providers.ollama.models does not include qwen2.5:7b
  • somewhere the ref is bare qwen2.5:7b instead of fully-qualified ollama/qwen2.5:7b

2. EISDIR

  • The agent trying to read a directory is plausible.
  • The raw EISDIR surfacing is not ideal. Current code has guards intended to convert directory reads into a “not a file” style failure, so a raw EISDIR looks more like missing guardrails or a regression than expected UX.

3. SKILL.md size limit

#
  • Config key: skills.limits.maxSkillFileBytes
  • Current default: 256000 bytes

Example:

{
  skills: {
    limits: {
      maxSkillFileBytes: 512000,
    },
  },
}

4. One extra thing to check
If the OpenAI error is actually coming from memory embeddings fallback, not the chat model, set:

#
{
  agents: {
    defaults: {
      memorySearch: {
        fallback: "none",
      },
    },
  },
}

Please paste these next:

openclaw --version
openclaw models status --json
#

Yep, caught up now 🙂

Short version: I need the affected host’s

openclaw --version
openclaw models status --json

to separate misconfig from a real fallback bug.

What I’ve confirmed already:

  • fallbacks: [] disables the normal model fallback chain
  • I do not see a strict “never fall back during model resolution” switch
  • raw EISDIR bubbling up looks like missing guardrails/regression, not ideal expected behavior
  • skills.limits.maxSkillFileBytes is the knob, default is 256000

If you paste those two outputs, I’ll narrow it down fast.

floral roost
#

I’ve adjusted my skills configuration to avoid SKILL.md being skipped and to ensure skills are actually usable in prompts.

Current config:

{
"skills": {
"limits": {
"maxSkillsLoadedPerSource": 5,
"maxSkillsInPrompt": 4,
"maxSkillsPromptChars": 12000,
"maxSkillFileBytes": 512000
}
}
}

This resolves the “oversized SKILL.md” issue, but I want to confirm best practices.

Questions:

Is maxSkillsPromptChars = 12000 a reasonable upper bound, or is there a recommended range for stable performance?
How do these limits interact with the model context window (especially with Ollama models like qwen2.5:7b)?
Are there any guidelines to balance:
number of skills
prompt size
agent decision quality

I’m aiming for a stable setup where skills are reliably used without degrading reasoning.

cunning mossBOT
#

Yep, that config is a reasonable conservative setup, especially for a local-ish 7B-class model.

A few verified details from current code/docs:

  • default maxSkillsLoadedPerSource: 200
  • default maxSkillsInPrompt: 150
  • default maxSkillsPromptChars: 30000
  • default maxSkillFileBytes: 256000

So your config is much tighter than default, which is usually good for stability on Ollama.

Recommended take on your values

maxSkillsPromptChars = 12000

  • Yes, that’s a sane upper bound.
  • For smaller/local models, I’d rather be around 8k to 12k than 30k.
  • Roughly, 12000 chars is on the order of a few thousand tokens, depending on tokenizer.
#

How the limits interact

They apply in this order:

  1. maxSkillsInPrompt trims the visible skills list by count first
  2. then maxSkillsPromptChars checks total prompt size
  3. if it’s too large, OpenClaw switches to compact format (drops descriptions)
  4. if it still doesn’t fit, it truncates further

Important bit: this cap is for the available skills catalog in the system prompt, not the full SKILL.md contents.
The full SKILL.md cost only happens later if the agent actually reads that skill.

Practical guidance for qwen2.5:7b

For a setup like yours, I’d aim for:

  • 3 to 8 visible skills
#
  • short, very distinct descriptions
  • concise SKILL.md files
  • avoid giant overlapping skills

Your current:

  • maxSkillsInPrompt: 4
  • maxSkillsPromptChars: 12000

…is a solid starting point.

One caution

maxSkillsLoadedPerSource: 5 is fine if you want a curated set.

But it affects discovery, not just prompt size. So if a 6th valid skill exists in a source, it may never load at all. If skills seem to disappear unexpectedly, raise that first.

Best practice summary

#

I’d recommend:

  • keep maxSkillsInPrompt low
  • keep descriptions sharp, one line, non-overlapping
  • keep SKILL.md concise, move long reference material to separate files if needed
  • use openclaw skills check after changes

So, short answer: 12000 is reasonable, and for qwen2.5:7b I’d prefer that over the 30000 default.
If you want, I can help you tune this into a “small-model safe” profile next.

floral roost
#

29 "agents": {
30 "defaults": {
31 "memorySearch": {
32 "enabled": true,
33 "fallback": "none",
34 "provider": "local",
35 "sources": ["memory", "sessions"],
36 "experimental": {
37 "sessionMemory": true
38 }
39 }
40 }
41 },

invalid character '"' at 34:9

probably can't make anything of the "fallback": "none",?

cunning mossBOT
#

Yep, I can make something of that, and "fallback": "none" is not the problem.

That whole block is valid config by itself. These keys are real:

  • agents.defaults.memorySearch.provider
  • agents.defaults.memorySearch.fallback
  • agents.defaults.memorySearch.sources
  • agents.defaults.memorySearch.experimental.sessionMemory

So the parse error is probably from the surrounding syntax, usually one of:

  • missing comma before "agents"
  • missing opening { earlier in the file
  • pasting this block in the wrong nesting level
  • stray character / broken line above line 34

Use this exact shape:

#
{
  "agents": {
    "defaults": {
      "memorySearch": {
        "enabled": true,
        "provider": "local",
        "fallback": "none",
        "sources": ["memory", "sessions"],
        "experimental": {
          "sessionMemory": true
        }
      }
    }
  }
}
#

If this is being merged into an existing openclaw.json, the most likely real issue is just a missing comma right before the "agents" block.

If you want, paste 10 lines above and 10 lines below that section and I’ll spot the syntax bug.

floral roost
#

"bind": "loopback",
14 "tailscale": {
15 "mode": "off",
16 "resetOnExit": false
17 }
18 },
19 "wizard": {
20 "lastRunAt": "2026-04-11T13:18:39.146Z",
21 "lastRunVersion": "2026.4.10",
22 "lastRunCommand": "onboard",
23 "lastRunMode": "local"
24 },
25 "meta": {
26 "lastTouchedVersion": "2026.4.12",
27 "lastTouchedAt": "2026-04-13T14:05:53.198Z"
28 },
29 "agents": {
30 "defaults": {
31 "memorySearch": {
32 "enabled": true,
33 "fallback": "none",
34 "provider": "local",
35 "sources": ["memory", "sessions"],
36 "experimental": {
37 "sessionMemory": true
38 }
39 }
40 }
41 },
42 "plugins": {
43 "slots": {
44 "memory": "memory-core"
45 },
46 "entries": {
47 "ollama": {
48 "enabled": true,
49 "config": {}

cunning mossBOT
#

This pasted excerpt looks syntactically fine to me.

So, good news, the problem is not:

  • "fallback": "none"
  • "provider": "local"
  • "sources": ["memory", "sessions"]
  • "experimental": { "sessionMemory": true }

Those are all valid there.

What that means instead:

  • the real syntax error is probably outside this excerpt
  • most likely before line 13 or after line 49
  • parser line numbers often point at the next token after the real mistake
#

Two likely candidates:

  1. a missing comma or brace above "bind": "loopback"
  2. missing closing braces after the plugins.entries.ollama.config block

So yes, I can make something of it: your memorySearch block is okay.

If you paste from the very first { of the file down through the closing braces after plugins, I can spot the exact broken character.

cunning mossBOT
#

Short version:

  • SOUL.md = who the agent is

    • persona
    • tone
    • boundaries
    • blunt vs warm vs funny
    • “how should this assistant feel to talk to?”
  • USER.md = who the user is

    • name
    • how to address them
    • timezone
    • preferences
    • important context about the human(s) being served

Good rule of thumb: