{"record":{"id":"8fed490b4f258e00","repo":"immich-app/immich","slug":"geodata-file-cities500-not-found","errorCode":null,"errorMessage":"Geodata file ${cities500} not found","messagePattern":"Geodata file (.+?) not found","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/repositories/map.repository.ts","lineNumber":274,"sourceCode":"                )`.execute(manager);\n      await manager.schema.dropTable('geodata_places').execute();\n      await manager.schema.alterTable('geodata_places_tmp').renameTo('geodata_places').execute();\n    });\n    await this.db.schema\n      .createIndex('IDX_geodata_gist_earthcoord')\n      .on('geodata_places')\n      .using('gist')\n      .expression(sql`ll_to_earth_public(latitude, longitude)`)\n      .execute();\n    await this.loadCities500(admin1, admin2);\n    await this.createGeodataIndices();\n  }\n\n  private async loadCities500(admin1Map: Map<string, string>, admin2Map: Map<string, string>) {\n    const { resourcePaths } = this.configRepository.getEnv();\n    const cities500 = resourcePaths.geodata.cities500;\n    if (!existsSync(cities500)) {\n      throw new Error(`Geodata file ${cities500} not found`);\n    }\n\n    this.logger.log(`Starting geodata import`);\n    const startTime = performance.now();\n\n    const input = createReadStream(cities500, { highWaterMark: 512 * 1024 * 1024 });\n    let bufferGeodata = [];\n    const lineReader = readLine.createInterface({ input });\n    let count = 0;\n\n    let futures = [];\n    for await (const line of lineReader) {\n      const lineSplit = line.split('\\t');\n      if ((lineSplit[7] === 'PPLX' && lineSplit[8] !== 'AU') || lineSplit[7] === 'PPLH') {\n        continue;\n      }\n\n      const geoData = {","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/repositories/map.repository.ts#L256-L292","documentation":"loadCities500 verifies that the cities500 geodata file (path from resourcePaths.geodata.cities500 in the env config) exists before importing it during the map geodata import. If existsSync reports the file missing, it aborts the import with this error, since the stream/file read would otherwise fail ungracefully. It indicates a deployment/configuration problem: the geodata asset was never downloaded or the configured path is wrong.","triggerScenarios":"importGeodata() -> loadCities500() runs and existsSync(cities500) returns false, i.e. the path in config resourcePaths.geodata.cities500 does not exist on disk at import time.","commonSituations":"Docker image or deploy artifact shipped without the cities500 download step; GEODATA path env var misconfigured; volume mount missing the geodata directory; file deleted by cleanup job; wrong relative path because the server was started from a different working directory.","solutions":["Download/place the cities500 geodata file (e.g. GeoNames cities500.txt) at the configured path","Verify the geodata path in the env config (configRepository.getEnv().resourcePaths.geodata.cities500) points to the actual file location","Check the container/volume mount actually includes the geodata directory","Re-run the geodata import after the file is present"],"exampleFix":"// before (config points to missing file)\n// GEODATA_CITIES500=./data/cities500.txt   (file absent)\n// after\n// curl -o ./data/cities500.txt https://download.geonames.org/export/dump/cities500.zip && unzip cities500.zip","handlingStrategy":"validation","validationCode":"import { existsSync } from 'fs';\nconst { cities500 } = config.getEnv().resourcePaths.geodata;\nif (!existsSync(cities500)) throw new Error(`Geodata missing: ${cities500} — run the geodata download step first`);","typeGuard":"const hasGeodata = (p: string): p is string => typeof p === 'string' && p.length > 0 && existsSync(p);","tryCatchPattern":"try {\n  await mapRepo.importGeodata();\n} catch (e) {\n  if (String(e.message).includes('not found')) {\n    logger.error('Geodata assets missing; skipping map import', { path: e.message });\n  } else throw e;\n}","preventionTips":["Download geodata files in the image build / setup script (cities500 + admin1/admin2)","Assert geodata presence in a startup health check before enabling map features","Use absolute paths resolved from a known root instead of cwd-relative paths","Mount geodata as a persistent volume in containerized deployments"],"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"}