{"record":{"id":"5f6afddabaca82f4","repo":"siyuan-note/siyuan","slug":"catalog-has-no-providers-with-api-endpoints-and-va","errorCode":null,"errorMessage":"catalog has no providers with API endpoints and valid models","messagePattern":"catalog has no providers with API endpoints and valid models","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"kernel/agent/modelmeta_online.go","lineNumber":250,"sourceCode":"\t\t\t\tsuffix = suffix[idx+1:]\n\t\t\t}\n\t\t\tsetConsistentModelContextLimit(providerCatalog.suffixes, providerAmbiguousSuffixes, suffix, limit)\n\t\t\tsetConsistentModelContextLimit(catalog.models, ambiguousModels, lower, limit)\n\t\t\tsetConsistentModelContextLimit(catalog.suffixes, ambiguousSuffixes, suffix, limit)\n\t\t}\n\t\tif len(providerCatalog.models) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tapis := append([]string{provider.API}, modelsDevAPIAliases[providerID]...)\n\t\tfor _, providerAPI := range apis {\n\t\t\tapi := normalizeModelsDevAPI(providerAPI)\n\t\t\tif api != \"\" {\n\t\t\t\tcatalog.providers[api] = providerCatalog\n\t\t\t}\n\t\t}\n\t}\n\tif len(catalog.providers) == 0 {\n\t\treturn nil, errors.New(\"catalog has no providers with API endpoints and valid models\")\n\t}\n\treturn catalog, nil\n}\n\nfunc setUniqueModelContextLimit(limits map[string]int, model string, limit int) {\n\tif existing := limits[model]; existing == 0 || existing == limit {\n\t\tlimits[model] = limit\n\t\treturn\n\t}\n\tdelete(limits, model)\n}\n\nfunc setConsistentModelContextLimit(limits map[string]int, ambiguous map[string]bool, model string, limit int) {\n\tif ambiguous[model] {\n\t\treturn\n\t}\n\tif existing := limits[model]; existing != 0 && existing != limit {\n\t\tdelete(limits, model)","sourceCodeStart":232,"sourceCodeEnd":268,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/agent/modelmeta_online.go#L232-L268","documentation":"After decoding and normalizing the models.dev catalog, no provider entry had both a usable API endpoint (api != \"\") and at least one valid model context limit, so the constructed catalog would be useless and is rejected. This validates semantic content rather than mere JSON shape.","triggerScenarios":"The catalog response contains providers but every one lacks an API endpoint field or fails setUniqueModelContextLimit validation for all its models — e.g. a format drift in the upstream models.dev data where fields were renamed (e.g. 'api' or per-model context fields moved).","commonSituations":"Upstream models.dev schema change renaming the api or context-length fields; partial/degraded catalog data during an upstream migration; an old SiYuan build parsing a newer catalog format.","solutions":["Inspect the raw catalog JSON to confirm the expected 'api' and model context fields are present","Update SiYuan (or the parser) to match the current upstream models.dev schema","Retry later in case upstream is mid-migration and serving degraded data","Continue with the cached catalog or manually specify context lengths for your model if the app supports it"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"valid := 0\nfor _, p := range providers { if p.API != \"\" && len(p.Models) > 0 { valid++ } }\nif valid == 0 { return nil, errors.New(\"catalog payload lacks usable providers\") }","typeGuard":null,"tryCatchPattern":"catalog, err := fetchModelsDevContextCatalog(ctx)\nif err != nil { log.Printf(\"catalog unusable (%v); keeping previous catalog\", err); catalog = cachedCatalog }","preventionTips":["Write a contract test that parses a saved models.dev fixture on every release","Validate catalog field names (api, model context limits) against the upstream schema before adopting","Keep a versioned fallback catalog bundled with the app"],"tags":["catalog","schema","upstream","http"],"backgroundTag":"unexpected-response-shape","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}