langgenius/dify · error · BadYamlFormatError
bad YAML format
Error message
bad YAML format
What it means
BadYamlFormatError (BaseError, ClientError → exit 1) thrown by loadYaml (store.ts:268) when js-yaml's loadAll throws a YAMLException OR when the input yields more than one YAML document (store.ts:264-265 explicitly rejects multi-doc streams). The wrapper enriches the error with the file path, the parser's reason, line/column, and an excerpt of the offending region (see excerpt() in store/errors.ts). loadYaml runs on every YamlStore read/write path (doGet/doSet/doUnset/getTyped/setTyped), so any corruption in hosts.yml or another store file surfaces here.
Source
Thrown at cli/src/store/store.ts:268
const next = current[part]
if (next === null || next === undefined || typeof next !== 'object') return
current = next as Record<string, unknown>
}
if (!(lastKey in current)) return
delete current[lastKey]
this.setRawContent(dump(data, { lineWidth: -1, noRefs: true }))
}
}
function loadYaml(raw: string | undefined, file_path: string): Record<string, unknown> | null {
if (raw === undefined) return null
try {
const documents = loadAll(raw, { schema: YAML_LOAD_SCHEMA })
if (documents.length > 1)
throw new YAMLException('expected a single document in the stream, but found more')
return (documents[0] ?? {}) as Record<string, unknown>
} catch (err) {
if (err instanceof YAMLException) throw new BadYamlFormatError(file_path, raw, err)
throw err
}
}
/**
* OS-keyring-based storage primitive. Sits at the same layer as
* `FileBasedStore`: implements `Store` with each `Key<T>` corresponding to a
* single keyring entry under the configured service. Values are JSON-encoded.
*/
export class KeyringBasedStore implements Store {
private readonly service: string
constructor(service: string) {
this.service = service
}
async get<T>(key: Key<T>): Promise<T> {
try {View on GitHub (pinned to ef8544b173)
Solutions
- Read the error: it names the file, the reason, line/column, and shows a snippet with a `^` marker.
- Open the file at the indicated line and fix the indentation/syntax; use spaces, never tabs.
- Resolve any merge-conflict markers; ensure a single YAML document (no `---` separators).
- If the file is unrecoverable, the hint suggests removing it to reset — back it up first, then `rm <path>`; difyctl will recreate it on next write (you will need to `difyctl auth login` again for hosts.yml).
- Validate with a linter (`yamllint <path>`) before re-running.
Example fix
# before — tabs / bad indent in hosts.yml default: host: https://cloud.dify.ai # tab — YAML rejects tabs email: a@b.com # inconsistent indent # after — spaces, consistent indent default: host: https://cloud.dify.ai email: a@b.com # nuclear option — reset and re-login mv ~/.config/difyctl/hosts.yml ~/.config/difyctl/hosts.yml.bak difyctl auth login
Defensive patterns
Strategy: try-catch
Validate before calling
// validate the YAML file is parseable and single-document before difyctl touches it
import { loadAll } from 'js-yaml'
import { readFileSync } from 'node:fs'
function validateStoreYaml(path: string): void {
const docs = loadAll(readFileSync(path, 'utf8'))
if (docs.length > 1) throw new Error(`${path} must contain a single YAML document`)
} Try / catch
import { BadYamlFormatError } from '@/store/errors'
try {
await store.getTyped<Registry>()
} catch (err) {
if (err instanceof BadYamlFormatError) {
// err.message has file path + line/column + snippet
console.error(`store corrupt: ${err.message}`)
// recovery: back up and reset
throw err
}
throw err
} Prevention
- Never hand-edit hosts.yml with tabs; use spaces and a YAML-aware editor.
- Run `yamllint` after manual edits.
- Avoid multi-document YAML (`---` separators) — the store rejects it.
- Back up the file before resetting; removing it loses auth state.
When it happens
Trigger: Hand-editing hosts.yml and breaking indentation, using tabs, unbalanced quotes, or a stray `:`. Also: a multi-document file (--- separator) which the store rejects; a file written by a newer difyctl using tags the loaded schema rejects; merge keys (!) handled via CORE_SCHEMA.withTags — only binary/merge/omap/pairs/set/timestamp are allowed. Also accidental binary/JSON content saved as .yml.
Common situations: Manual edit of hosts.yml to fix something; merge conflict resolution that left conflict markers (<<<<<<<, =======, >>>>>>>) which YAML can't parse; an editor inserting tabs; sync tools (Dropbox, git) writing a partial file; downgrade after an upgrade changed the schema.
Related errors
- concurrent access detected
- expected integer, got ${JSON.stringify(raw)}
- expected boolean, got ${JSON.stringify(raw)}
- UsageInvalidFlag
- Qdrant URL is required.
AI-assisted analysis of langgenius/dify@ef8544b173 (2026-08-12).
Data as JSON: /api/errors/e556c09a70c96abe.
Report an issue: GitHub.