{"record":{"id":"9a2746db01252577","repo":"microsoft/markitdown","slug":"failed-to-verify-exiftool-version","errorCode":null,"errorMessage":"Failed to verify ExifTool version.","messagePattern":"Failed to verify ExifTool version\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"packages/markitdown/src/markitdown/converters/_exiftool.py","lineNumber":36,"sourceCode":"        return {}\n\n    # Verify exiftool version\n    try:\n        version_output = subprocess.run(\n            [exiftool_path, \"-ver\"],\n            capture_output=True,\n            text=True,\n            check=True,\n        ).stdout.strip()\n        version = _parse_version(version_output)\n        min_version = (12, 24)\n        if version < min_version:\n            raise RuntimeError(\n                f\"ExifTool version {version_output} is vulnerable to CVE-2021-22204. \"\n                \"Please upgrade to version 12.24 or later.\"\n            )\n    except (subprocess.CalledProcessError, ValueError) as e:\n        raise RuntimeError(\"Failed to verify ExifTool version.\") from e\n\n    # Run exiftool\n    cur_pos = file_stream.tell()\n    try:\n        output = subprocess.run(\n            [exiftool_path, \"-json\", \"-\"],\n            input=file_stream.read(),\n            capture_output=True,\n            text=False,\n        ).stdout\n\n        return json.loads(\n            output.decode(locale.getpreferredencoding(False)),\n        )[0]\n    finally:\n        file_stream.seek(cur_pos)\n","sourceCodeStart":18,"sourceCodeEnd":53,"githubUrl":"https://github.com/microsoft/markitdown/blob/fd239d5d2be43d9b68329730206b9312c7d5a388/packages/markitdown/src/markitdown/converters/_exiftool.py#L18-L53","documentation":"Before extracting metadata, MarkItDown runs `exiftool -ver` with check=True and parses the output with _parse_version. If the subprocess exits non-zero (exiftool missing, broken, or unusable) or the version string cannot be parsed into numeric components (raises ValueError), this generic RuntimeError wraps the underlying cause. It means exiftool exists on PATH per the earlier lookup but cannot be executed or version-queried successfully.","triggerScenarios":"exiftool binary on PATH is corrupt, not executable, or a wrapper script that fails; platform-specific execution failures (e.g. Windows requiring perl, or the standalone exiftool.exe renamed); exiftool -ver printing unexpected text (e.g. warnings mixed in, or a non-numeric version) causing _parse_version to raise ValueError; architecture mismatch (x86 binary on ARM).","commonSituations":"The exiftool executable found via shutil.which is a stub or broken symlink; exiftool needs a missing shared library / perl module; PATH resolves to the wrong binary (e.g. a directory named 'exiftool' shadowing the tool); restricted environments (noexec mounts, sandboxed CI) preventing subprocess execution.","solutions":["Run `exiftool -ver` in the same shell/environment where your code runs and inspect the error; fix whatever it reports","Ensure a real, executable exiftool >= 12.24 is first on PATH (test with `which -a exiftool`)","On Windows use the standalone exiftool.exe; make sure it is named exiftool(-k).exe renamed to exiftool.exe and executable","If the environment cannot run subprocesses, install exiftool through a package manager that ships a self-contained binary (e.g. static build)"],"exampleFix":"# before: PATH contains a broken wrapper\n$ exiftool -ver\n/usr/bin/env: 'perl': No such file or directory\n\n# after: install perl or a self-contained build\n$ apt-get install -y perl libimage-exiftool-perl\n$ exiftool -ver\n12.76","handlingStrategy":"validation","validationCode":"import shutil, subprocess\n\ndef exiftool_works() -> bool:\n    path = shutil.which(\"exiftool\")\n    if not path:\n        return False\n    try:\n        subprocess.run([path, \"-ver\"], capture_output=True, check=True, timeout=10)\n        return True\n    except Exception:\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    result = MarkItDown().convert(\"photo.jpg\")\nexcept RuntimeError as e:\n    if \"Failed to verify ExifTool version\" in str(e):\n        logger.error(\"exiftool present but not executable/version-unparseable: %s\", e)\n        raise","preventionTips":["Smoke-test `exiftool -ver` in your environment during deployment health checks","Install exiftool from official releases or maintained package managers, not copied binaries","Keep PATH clean of shadowing files named exiftool"],"tags":["exiftool","subprocess","environment","external-binary","version-check"],"backgroundTag":null,"analyzedSha":"fd239d5d2be43d9b68329730206b9312c7d5a388","analyzedAt":"2026-08-14T15:47:51.745Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}