{"record":{"id":"e1dbeeea5d241e66","repo":"immich-app/immich","slug":"unable-to-complete-move-file-checksum-mismatch-newchecksum","errorCode":null,"errorMessage":"Unable to complete move. File checksum mismatch: ${newChecksum.toString('base64')} !== ${checksum.toString('base64')}","messagePattern":"Unable to complete move\\. File checksum mismatch: (.+?) !== (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/src/cores/storage.core.ts","lineNumber":300,"sourceCode":"    const newStat = await this.storageRepository.stat(newPath);\n    const oldPathSize = assetInfo ? assetInfo.sizeInBytes : oldStat.size;\n    const newPathSize = newStat.size;\n    this.logger.debug(`File size check: ${newPathSize} === ${oldPathSize}`);\n    if (newPathSize !== oldPathSize) {\n      this.logger.warn(`Unable to complete move. File size mismatch: ${newPathSize} !== ${oldPathSize}`);\n      return false;\n    }\n    const repos = {\n      configRepo: this.configRepository,\n      metadataRepo: this.systemMetadataRepository,\n      logger: this.logger,\n    };\n    const config = await getConfig(repos, { withCache: true });\n    if (assetInfo && config.storageTemplate.hashVerificationEnabled) {\n      const { checksum } = assetInfo;\n      const newChecksum = await this.cryptoRepository.hashFile(newPath);\n      if (!newChecksum.equals(checksum)) {\n        this.logger.warn(\n          `Unable to complete move. File checksum mismatch: ${newChecksum.toString('base64')} !== ${checksum.toString(\n            'base64',\n          )}`,\n        );\n        return false;\n      }\n      this.logger.debug(`File checksum check: ${newChecksum.toString('base64')} === ${checksum.toString('base64')}`);\n    }\n    return true;\n  }\n\n  ensureFolders(input: string) {\n    this.storageRepository.mkdirSync(dirname(input));\n  }\n\n  removeEmptyDirs(folder: StorageFolder) {\n    return this.storageRepository.removeEmptyDirs(StorageCore.getBaseFolder(folder));\n  }","sourceCodeStart":282,"sourceCodeEnd":318,"githubUrl":"https://github.com/immich-app/immich/blob/e55ac299a4ec7cb372e35dbf2c6c05ee9ce77f6c/server/src/cores/storage.core.ts#L282-L318","documentation":"When storage-template hash verification is enabled and the move is for an asset, the copied file's SHA-1 checksum is compared to the checksum stored for the asset. Any difference fails verification, and this warning is logged with both base64 checksums before the caller rolls back the copy.","triggerScenarios":"moveFile -> verifyNewPathContentsMatchesExpected with assetInfo present and config.storageTemplate.hashVerificationEnabled=true; cryptoRepository.hashFile(newPath) differs from assetInfo.checksum — copy corrupted data or the stored checksum is stale/wrong.","commonSituations":"Bit rot or corruption during copy on failing disks; asset checksum recorded before a later metadata-side change; mismatched checksum algorithm after version migration; file mutated by another process between copy and hash.","solutions":["Verify the stored checksum against the ORIGINAL file; if the original also mismatches, re-generate checksums","Check disk health (SMART) on both source and destination","Re-copy the file and re-run verification","Temporarily disable hashVerificationEnabled to isolate whether size or hash check fails, then re-enable"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"const expected = assetInfo.checksum.toString('base64');\nconst actual = (await hashFile(newPath)).toString('base64');\nif (expected !== actual) await fs.promises.unlink(newPath); // roll back before proceeding","typeGuard":null,"tryCatchPattern":"if (!(await verifyNewPathContentsMatchesExpected(oldPath, newPath, assetInfo))) {\n  await storage.unlink(newPath);\n  logger.warn(`hash mismatch expected=${expected}`);\n  return moveFailed();\n}","preventionTips":["Run SMART/disk health checks on storage volumes","Keep hashVerificationEnabled true in production","Recompute asset checksums if stored values are suspected stale","Avoid concurrent writes to the same asset during moves"],"tags":["filesystem","checksum","verification","integrity"],"backgroundTag":"checksum-mismatch","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"}