{"record":{"id":"cc80d8f5919a49c2","repo":"immich-app/immich","slug":"you-may-not-access-another-user-s-locked-timeline","errorCode":null,"errorMessage":"You may not access another user's locked timeline","messagePattern":"You may not access another user's locked timeline","errorType":"exception","errorClass":"BadRequestException","httpStatus":400,"severity":"error","filePath":"server/src/services/timeline.service.ts","lineNumber":64,"sourceCode":"\n  private async timeBucketChecks(auth: AuthDto, dto: TimeBucketDto) {\n    if (dto.visibility === AssetVisibility.Locked) {\n      requireElevatedPermission(auth);\n    }\n\n    if (dto.albumId) {\n      await this.requireAccess({ auth, permission: Permission.AlbumRead, ids: [dto.albumId] });\n    } else {\n      dto.userId ||= auth.user.id;\n    }\n\n    if (dto.userId) {\n      await this.requireAccess({ auth, permission: Permission.TimelineRead, ids: [dto.userId] });\n      if (dto.visibility === AssetVisibility.Archive) {\n        await this.requireAccess({ auth, permission: Permission.ArchiveRead, ids: [dto.userId] });\n      }\n      if (dto.visibility === AssetVisibility.Locked && dto.userId !== auth.user.id) {\n        throw new BadRequestException(\"You may not access another user's locked timeline\");\n      }\n    }\n\n    if (dto.tagId) {\n      await this.requireAccess({ auth, permission: Permission.TagRead, ids: [dto.tagId] });\n    }\n\n    if (auth.sharedLink && !auth.sharedLink.showExif) {\n      dto.withCoordinates = false;\n    }\n\n    if (dto.withPartners) {\n      const isRequestedLocked = dto.visibility === AssetVisibility.Locked;\n      const isRequestedArchived = dto.visibility === AssetVisibility.Archive || dto.visibility === undefined;\n      const isRequestedFavorite = dto.isFavorite === true || dto.isFavorite === false;\n      const isRequestedTrash = dto.isTrashed === true;\n\n      if (isRequestedLocked || isRequestedArchived || isRequestedFavorite || isRequestedTrash) {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/immich-app/immich/blob/199723261c6ffa897fec8ccdaea6359e39c37cc3/server/src/services/timeline.service.ts#L46-L82","documentation":"Thrown (as BadRequestException) by TimelineService when the requested visibility is AssetVisibility.Locked and the target userId is not the authenticated user. Locked timelines are private by design; even admins/partners cannot browse another user's locked assets through the timeline endpoint.","triggerScenarios":"GET timeline/buckets or timeline/search with visibility=Locked and userId pointing at a different user than auth.user.id.","commonSituations":"Admin tooling tries to audit locked assets of a user; partner UI accidentally requests a partner's locked scope; client passed the wrong userId.","solutions":["Omit visibility=Locked when querying another user; locked assets are only self-visible.","If you need the current user's locked items, ensure dto.userId equals auth.user.id (or omit userId).","Use the admin asset list endpoint if a true audit of locked assets is required."],"exampleFix":"// before\nbuckets({ userId: otherUserId, visibility: AssetVisibility.Locked });\n// after\nbuckets({ userId: auth.user.id, visibility: AssetVisibility.Locked });","handlingStrategy":"validation","validationCode":"function canViewLocked(authUserId: string, targetUserId: string | undefined, vis: AssetVisibility) {\n  return vis !== AssetVisibility.Locked || targetUserId === undefined || targetUserId === authUserId;\n}\nif (!canViewLocked(auth.user.id, dto.userId, dto.visibility)) { /* hide the locked filter */ }","typeGuard":null,"tryCatchPattern":"try { await timelineApi.buckets(dto); }\ncatch (e) {\n  if (e instanceof BadRequestException && /locked timeline/.test(e.message)) {\n    // clear visibility=Locked when userId != self\n  }\n}","preventionTips":["Hide the 'Locked' filter when viewing another user's timeline.","Default dto.userId to auth.user.id for self views.","Use admin asset endpoints for cross-user audits instead of timeline."],"tags":["timeline","authorization","locked","validation","bad-request"],"backgroundTag":null,"analyzedSha":"199723261c6ffa897fec8ccdaea6359e39c37cc3","analyzedAt":"2026-08-12T04:54:27.085Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}