{"record":{"id":"bcc18c0ffb220862","repo":"immich-app/immich","slug":"geodata-file-filepath-not-found","errorCode":null,"errorMessage":"Geodata file ${filePath} not found","messagePattern":"Geodata file (.+?) not found","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/repositories/map.repository.ts","lineNumber":349,"sourceCode":"      await this.db.insertInto('geodata_places').values(bufferGeodata).execute();\n      count += bufferGeodata.length;\n    }\n\n    await Promise.all(futures);\n\n    const duration = performance.now() - startTime;\n    const seconds = duration / 1000;\n    const recordsPerSecond = Math.round(count / seconds);\n\n    this.logger.log(\n      `Successfully imported ${count} geodata records in ${seconds.toFixed(2)}s (${recordsPerSecond} records/second)`,\n    );\n  }\n\n  private async loadAdmin(filePath: string) {\n    if (!existsSync(filePath)) {\n      this.logger.error(`Geodata file ${filePath} not found`);\n      throw new Error(`Geodata file ${filePath} not found`);\n    }\n\n    const input = createReadStream(filePath, { highWaterMark: 512 * 1024 * 1024 });\n    const lineReader = readLine.createInterface({ input });\n\n    const adminMap = new Map<string, string>();\n    for await (const line of lineReader) {\n      const lineSplit = line.split('\\t');\n      adminMap.set(lineSplit[0], lineSplit[1]);\n    }\n\n    return adminMap;\n  }\n\n  private createGeodataIndices() {\n    return Promise.all([\n      sql`ALTER TABLE geodata_places ADD PRIMARY KEY (id) WITH (FILLFACTOR = 100)`.execute(this.db),\n      this.db.schema","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/map.repository.ts#L331-L367","documentation":"loadAdmin checks that an admin1/admin2 geodata file exists before streaming it into a Map. It logs and throws this error when existsSync(filePath) is false. Like loadCities500, it signals a missing geodata asset or a misconfigured file path in the resourcePaths config.","triggerScenarios":"importGeodata() invokes loadAdmin() (via admin1/admin2 callers) with a filePath that does not exist on disk, so existsSync(filePath) fails and the error is thrown.","commonSituations":"admin1Codes/admin2 geodata files not downloaded during setup; path typo in env config; missing volume mount in container; renamed file after a GeoNames data update.","solutions":["Place the admin1/admin2 geodata files at the configured filePath","Fix the resourcePaths.geodata admin file paths in the env config","Ensure the geodata directory is included in the deployment (image build step or volume mount)","Verify file permissions allow the server process to stat/read the file"],"exampleFix":"// before\n// geodata.admin1 = ./data/admin1Codes.txt (missing)\n// after\n// curl -o ./data/admin1Codes.txt https://download.geonames.org/export/dump/admin1CodesASCII.txt","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nfor (const f of [admin1Path, admin2Path]) {\n  if (!existsSync(f)) throw new Error(`Admin geodata missing: ${f}`);\n}","typeGuard":"const fileExists = (p: unknown): p is string => typeof p === 'string' && existsSync(p);","tryCatchPattern":"try {\n  await mapRepo.importGeodata();\n} catch (e) {\n  if (String(e.message).startsWith('Geodata file')) {\n    logger.warn(`Admin geodata unavailable: ${e.message}`);\n    return; // degrade gracefully\n  }\n  throw e;\n}","preventionTips":["Bundle admin1/admin2 files in the same download step as cities500","Log the resolved absolute path at startup so misconfigurations are visible early","Pin/verify geodata file versions after provider data updates","Verify file read permissions for the server's runtime user"],"tags":["geodata","file-not-found","configuration"],"backgroundTag":"file-not-found","analyzedSha":"e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c","analyzedAt":"2026-09-15T07:20:19.675Z","contentChangedAt":"2026-09-15T07:20:19.675Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}