{"record":{"id":"c8dcf57ce70e319e","repo":"jax-ml/jax","slug":"no-vjp-defined-for-custom-vjp-function-self-f-n","errorCode":null,"errorMessage":"No VJP defined for custom_vjp function {self.f.__name__} using defvjp.","messagePattern":"No VJP defined for custom_vjp function (.+?) using defvjp\\.","errorType":"exception","errorClass":"AttributeError","httpStatus":null,"severity":"error","filePath":"jax/_src/hijax.py","lineNumber":944,"sourceCode":"    update_wrapper(self, f)\n    self.f = f\n\n  def defvjp(self, fwd, bwd, *, symbolic_zeros=False, optimize_remat=False):\n    self.fwd = fwd\n    self.bwd = bwd\n    self.symz = symbolic_zeros\n    self.opt_remat = optimize_remat\n\n  def defvjp_with_logs(self, fwd, bwd, *, symbolic_zeros=False,\n                       optimize_remat=False):\n    self.defvjp(fwd, bwd, symbolic_zeros=symbolic_zeros,\n                optimize_remat=optimize_remat)\n    self.with_logs = True\n\n  def __call__(self, *args, **kwargs):\n    if not self.fwd or not self.bwd:\n      msg = f\"No VJP defined for custom_vjp function {self.f.__name__} using defvjp.\"\n      raise AttributeError(msg)\n\n    args = resolve_kwargs(self.f, args, kwargs)\n    if any(isinstance(l, core.Tracer) for i in self.static_argnums\n           for l in tree_leaves(args[i])):\n      raise UnexpectedTracerError(\"custom_vjp inputs marked with nondiff_argnums \"\n                                  \"must be static, not Tracers\")\n    if all(is_hashable(args[i]) for i in self.static_argnums):\n      traced = api.jit(self.f, static_argnums=(*self.static_argnums,)).trace(*args)\n    else:\n      # jit requires hashable static_argnums values, but classic custom_vjp\n      # accepted unhashable nondiff_argnums values, so close over them instead\n      which_static = [i in self.static_argnums for i in range(len(args))]\n      dyn_args, static_args = partition_list(which_static, args)\n      f = dyn_args_fun(self.f, self.static_argnums,\n                       tuple(map(WrapHashably, static_args)), len(args))\n      traced = api.jit(f).trace(*dyn_args)\n    args = tuple(Static(x) if i in self.static_argnums else x for i, x in enumerate(args))\n    consts, traced = traced.with_consts_as_arg()","sourceCodeStart":926,"sourceCodeEnd":962,"githubUrl":"https://github.com/jax-ml/jax/blob/1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb/jax/_src/hijax.py#L926-L962","documentation":"A @jax.custom_vjp-decorated function was called before any VJP rule was registered with defvjp. The wrapper raises AttributeError on __call__ because neither self.fwd nor self.bwd exists yet.","triggerScenarios":"Calling f(x) on a function decorated with @jax.custom_vjp without ever calling f.defvjp(f_fwd, f_bwd) (or defvjp_fwd/defvjp_bwd) beforehand.","commonSituations":"Refactoring where defvvp registration moved below the first call site or into a module that is no longer imported; copy-paste from custom_jvp examples where registration is optional; defining the decorated function in a library where the user must register the rule themselves.","solutions":["Register the rule before any call: f.defvjp(fwd, bwd)","If using the newer split API, ensure both defvjp_fwd and defvjp_bwd were invoked","Move registration to module top level right after the decorated definition so import order guarantees it"],"exampleFix":"// before\n@jax.custom_vjp\ndef f(x):\n  return x * 2\ny = f(3.)   # AttributeError\n// after\n@jax.custom_vjp\ndef f(x):\n  return x * 2\ndef f_fwd(x): return f(x), None\ndef f_bwd(_, ct): return (ct * 2,)\nf.defvjp(f_fwd, f_bwd)\ny = f(3.)","handlingStrategy":"validation","validationCode":"assert getattr(f, 'fwd', None) and getattr(f, 'bwd', None), 'call f.defvjp(fwd, bwd) before use'","typeGuard":null,"tryCatchPattern":"try:\n    f(x)\nexcept AttributeError as e:\n    if 'No VJP defined' in str(e):\n        f.defvjp(f_fwd, f_bwd)\n        f(x)","preventionTips":["Register defvvp at module scope immediately after decoration","Smoke-test decorated functions on import in libraries"],"tags":["jax","custom-vjp","missing-rule","autodiff"],"backgroundTag":"jax-custom-vjp-missing-defvjp","analyzedSha":"1e1c6a8fc06dfcd1247076ec5cae4640cea5d7bb","analyzedAt":"2026-08-27T09:53:25.647Z","schemaVersion":2},"datasetVersion":"2026-08-27T13:17:12.746Z"}