{"record":{"id":"62b23b49faf33c30","repo":"siyuan-note/siyuan","slug":"conf-language-26-62b23b","errorCode":null,"errorMessage":"Conf.Language(26)","messagePattern":"Conf\\.Language\\(26\\)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"kernel/model/asset_download.go","lineNumber":374,"sourceCode":"\t\treturn data, err\n\t}\n\tif err = checkAssetDownloadAccess(); err != nil {\n\t\treturn nil, err\n\t}\n\thandleCloudError := cloudRepoErrorHandler()\n\tif err = repo.EnsureFileChunks(file, newSyncContext()); err != nil {\n\t\thandleCloudError(err)\n\t\treturn nil, fmt.Errorf(\"%s: %w\", Conf.Language(376), err)\n\t}\n\treturn repo.OpenFile(file)\n}\n\n// readRepoFileWithAssets 将仓库实例的创建和历史分块补齐纳入来源读锁。\nfunc readRepoFileWithAssets(fileID string) ([]byte, *entity.File, error) {\n\tassetDownloadSourceMu.RLock()\n\tdefer assetDownloadSourceMu.RUnlock()\n\tif Conf.Repo == nil || len(Conf.Repo.Key) == 0 {\n\t\treturn nil, nil, errors.New(Conf.Language(26))\n\t}\n\trepo, err := newRepositoryWithAssetSourceLocked()\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tfile, err := repo.GetFile(fileID)\n\tif err != nil {\n\t\treturn nil, nil, err\n\t}\n\tif boxID := encryptedBoxIDFromRepoPath(file.Path); boxID != \"\" && !IsBoxUnlocked(boxID) {\n\t\treturn nil, nil, errors.New(Conf.Language(314))\n\t}\n\tdata, err := openRepoFileWithAssets(repo, file)\n\treturn data, file, err\n}\n\nfunc ensureRepoSnapshotComplete(repo *dejavu.Repo, indexID string) error {\n\tindex, err := repo.GetIndex(indexID)","sourceCodeStart":356,"sourceCodeEnd":392,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/kernel/model/asset_download.go#L356-L392","documentation":"readRepoFileWithAssets refuses to read any repository file when Conf.Repo is nil or Conf.Repo.Key is empty, returning the localized message Conf.Language(26) (roughly 'repo key not initialized'). The repo encryption key is required to construct the repository instance and decrypt chunks; without it no repo file can be opened.","triggerScenarios":"Any call to GetRepoFile, RollbackRepoSnapshotFile, OpenRepoSnapshotFile, or ExportRepoFile on a workspace where cloud sync/snapshot has never been configured, or where Conf.Repo.Key was lost (fresh clone, corrupted conf.json, switching workspaces).","commonSituations":"User tries to browse snapshot history on a brand-new workspace that never enabled cloud sync; config file was reset or migrated without carrying over the repo key; automated scripts call the repo APIs before initRepoKey ran.","solutions":["Enable cloud sync in Settings - About - Cloud (or run InitRepoKey) so Conf.Repo and its key are generated","If the key was lost, recover it from another synced device via Settings - About - Cloud - Repo Key copy/paste","Verify conf.json in the workspace contains the repo section with a non-empty Key","Only call these repo-read APIs after confirming the repo is initialized (e.g. via the /api/repo/getRepoKeyexists endpoint)"],"exampleFix":"// before\ndata, err := model.GetRepoFile(fileID) // 'repo key not set'\n// after\nif exist, _ := model.GetRepoKeyExists(); !exist {\n    return errors.New(\"repo key not initialized; enable cloud sync first\")\n}\ndata, err := model.GetRepoFile(fileID)","handlingStrategy":"validation","validationCode":"if conf.Conf.Repo == nil || len(conf.Conf.Repo.Key) == 0 {\n    return errors.New(\"repo key missing: enable cloud sync or copy the key from another device\")\n}","typeGuard":null,"tryCatchPattern":"data, err := model.GetRepoFile(fileID)\nif err != nil && strings.Contains(err.Error(), conf.Conf.Language(26)) {\n    return fmt.Errorf(\"call InitRepoKey / enable cloud sync first: %w\", err)\n}","preventionTips":["Initialize the repo key immediately after creating a workspace","Back up conf.json (contains the repo key) when migrating workspaces","Gate repo-read APIs behind a key-existence check (GetRepoKeyExists)","Never reset the workspace config without first copying the repo key"],"tags":["config","encryption","repo-key"],"backgroundTag":"missing-required-config-field","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"}