{"record":{"id":"c7a2f56be3f85ad5","repo":"jax-ml/jax","slug":"no-vjp-is-available","errorCode":null,"errorMessage":"No VJP is available","messagePattern":"No VJP is available","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"jax/_src/export/_export.py","lineNumber":295,"sourceCode":"\n    See documentation for in_shardings_jax.\n    \"\"\"\n    return tuple(\n      _get_named_sharding(named_sharding, mesh)\n      for named_sharding in self._out_named_shardings)\n\n  def has_vjp(self) -> bool:\n    \"\"\"Returns if this Exported supports VJP.\"\"\"\n    return self._get_vjp is not None\n\n  def vjp(self) -> Exported:\n    \"\"\"Gets the exported VJP.\n\n    Returns None if not available, which can happen if the Exported has been\n    loaded from an external format without a VJP.\n    \"\"\"\n    if self._get_vjp is None:\n      raise ValueError(\"No VJP is available\")\n    return self._get_vjp(self)\n\n  def serialize(self,\n                vjp_order: int = 0) -> bytearray:\n    \"\"\"Serializes an Exported.\n\n    Args:\n      vjp_order: The maximum vjp order to include. E.g., the value 2 means that we\n        serialize the primal functions and two orders of the ``vjp`` function. This\n        should allow 2nd order reverse mode differentiation of the deserialized\n        function. i.e., ``jax.grad(jax.grad(f))``.\n    \"\"\"\n    # Lazy load the serialization module, since flatbuffers is an optional\n    # dependency.\n    from jax._src.export.serialization import serialize\n    return serialize(self, vjp_order=vjp_order)\n\n  def call(self, *args, **kwargs):","sourceCodeStart":277,"sourceCodeEnd":313,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/export/_export.py#L277-L313","documentation":"Exported.vjp() returns the VJP of a serialized/exported function. If the Exported was loaded from an external serialization format that did not include VJP data, _get_vjp is None and this ValueError is raised.","triggerScenarios":"Loading an Exported from a StableHLO/external file (not created in-process with a VJP) and then calling .vjp(); deserializing a model saved for inference-only and requesting gradients; calling vjp() with vjp_order larger than what was exported.","commonSituations":"Serving/deployment pipelines that load exported models and later attempt fine-tuning or gradient-based analysis; mixing in-process exports (which carry VJPs) with file-loaded ones.","solutions":["Check availability first: if exported.vjp_available (or inspect _get_vjp) before calling vjp()","Re-export from the original JAX program with VJP included (serialize with the vjp captured)","For loaded exports, reconstruct gradients via a differentiating wrapper (jax.vjp) around the loaded callable instead"],"exampleFix":"# before\nexp = load_exported(path)\nvjp_fn = exp.vjp()  # ValueError\n\n# after\nexp = load_exported(path)\nvjp_fn = jax.vjp(exp.call) if not exp_has_vjp(exp) else exp.vjp()","handlingStrategy":"fallback","validationCode":"has_vjp = getattr(exported, '_get_vjp', None) is not None\nvjp_fn = exported.vjp() if has_vjp else jax.vjp(exported.call)","typeGuard":"def exported_has_vjp(exp) -> bool:\n    return getattr(exp, '_get_vjp', None) is not None","tryCatchPattern":"try:\n    vjp_fn = exported.vjp()\nexcept ValueError:\n    vjp_fn = jax.vjp(exported.call)  # differentiate around the loaded callable","preventionTips":["Check for VJP availability right after loading an export","When exporting models that need gradients later, serialize with VJP included","Document whether each loaded artifact is inference-only"],"tags":["jax","export","vjp","serialization"],"backgroundTag":"missing-serialized-gradient","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}