{"record":{"id":"3e9841e04749b6bf","repo":"CherryHQ/cherry-studio","slug":"openai-compatible-provider-requires-settings","errorCode":null,"errorMessage":"OpenAI Compatible provider requires settings","messagePattern":"OpenAI Compatible provider requires settings","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/aiCore/src/core/providers/core/initialization.ts","lineNumber":176,"sourceCode":"    webSearch:\n      (provider: GoogleGenerativeAIProvider) =>\n      (config: NonNullable<Parameters<GoogleGenerativeAIProvider['tools']['googleSearch']>[0]>) => ({\n        tools: { webSearch: provider.tools.googleSearch(config) }\n      }),\n    urlContext: (provider) => (config) => ({\n      tools: {\n        urlContext: provider.tools.urlContext(config)\n      }\n    })\n  }\n} as const satisfies ProviderExtensionConfig<GoogleGenerativeAIProviderSettings, GoogleGenerativeAIProvider, 'google'>)\n\nconst OpenAICompatibleExtension = ProviderExtension.create({\n  name: 'openai-compatible',\n  supportsImageGeneration: true,\n  create: (settings) => {\n    if (!settings) {\n      throw new Error('OpenAI Compatible provider requires settings')\n    }\n    return createOpenAICompatible(settings)\n  },\n  createRerankingModel: (modelId, settings) => {\n    if (!settings) {\n      throw new Error('OpenAI Compatible provider requires settings')\n    }\n    return createOpenAICompatibleRerankingModel(modelId, settings)\n  }\n} as const satisfies ProviderExtensionConfig<OpenAICompatibleProviderSettings, ProviderV3, 'openai-compatible'>)\n\nconst OpenAIExtension = ProviderExtension.create({\n  name: 'openai',\n  aliases: ['openai-response'] as const,\n  supportsImageGeneration: true,\n  create: createOpenAI,\n  toolFactories: {\n    webSearch:","sourceCodeStart":158,"sourceCodeEnd":194,"githubUrl":"https://github.com/CherryHQ/cherry-studio/blob/726446b54cd69ffe51a276638672f6d95ca0768c/packages/aiCore/src/core/providers/core/initialization.ts#L158-L194","documentation":"Raised by parse_skill_md() when the first line of a SKILL.md file is not exactly '---' (after strip). The parser expects YAML frontmatter delimited by opening and closing '---' lines; an absent opening delimiter means there is no frontmatter block to read name/description from. This fails fast rather than mis-parsing the body as frontmatter.","triggerScenarios":"A SKILL.md starts with prose (e.g. a title '# My Skill') and has no frontmatter; the file begins with a UTF-8 BOM so the first line is not literally '---'; the file is empty; the file uses a different delimiter (e.g. '+++').","commonSituations":"A skill hand-authored without frontmatter; a file copied from a Markdown template that begins with a heading; an editor saving with a BOM; a skill partially generated where the frontmatter was not written.","solutions":["Add YAML frontmatter beginning with a '---' line as the very first line of SKILL.md.","Include the required keys (name:, description:) between the opening and closing '---'.","Ensure the file is saved as UTF-8 without BOM so the first line matches '---'.","Use the skill-creator scaffolding to generate a valid SKILL.md skeleton."],"exampleFix":"# before\n# My Cool Skill\n\nDoes cool things.\n# after\n---\nname: my-cool-skill\ndescription: Does cool things.\n---\n\n# My Cool Skill","handlingStrategy":"validation","validationCode":"# Validate SKILL.md frontmatter structure before parsing.\nfrom pathlib import Path\ndef has_frontmatter(skill_path: Path) -> bool:\n    text = (skill_path / 'SKILL.md').read_text(encoding='utf-8-sig')  # strip BOM\n    lines = text.split('\\n')\n    return len(lines) > 0 and lines[0].strip() == '---' and any(l.strip() == '---' for l in lines[1:])","typeGuard":"def starts_with_frontmatter(path: Path) -> bool:\n    first = (path / 'SKILL.md').read_text(encoding='utf-8-sig').split('\\n', 1)[0].strip()\n    return first == '---'","tryCatchPattern":"from utils import parse_skill_md\ntry:\n    name, desc, content = parse_skill_md(skill_path)\nexcept ValueError as e:\n    if 'opening ---' in str(e):\n        print(f'{skill_path}: no frontmatter — add a leading --- block (name, description)')\n    raise","preventionTips":["Always start SKILL.md with a '---' frontmatter block containing name: and description:.","Save SKILL.md as UTF-8 without BOM so the first line is literally '---'.","Scaffold new skills with the skill-creator tool so frontmatter is generated correctly."],"tags":["python","skill-creator","frontmatter","yaml","parsing"],"backgroundTag":null,"analyzedSha":"726446b54cd69ffe51a276638672f6d95ca0768c","analyzedAt":"2026-08-12T17:30:37.448Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}