@@ -227,6 +227,12 @@ def __do_validate__(self, requirements: list[Requirement] | None = None) -> Vali
227227 logger .debug ("Aborting on first requirement failure" )
228228 terminate = True
229229 break
230+ # Unconditional abort: the metadata is unusable (e.g. not valid JSON),
231+ # so stop now instead of reporting false positives from later checks.
232+ if context .aborted :
233+ logger .debug ("Aborting validation: %s" , context .abort_reason )
234+ terminate = True
235+ break
230236 self .notify (ProfileValidationEvent (EventType .PROFILE_VALIDATION_END , profile = profile ))
231237 if terminate :
232238 break
@@ -287,6 +293,10 @@ def __init__(self, validator: Validator, settings: ValidationSettings):
287293 self ._properties : dict = {}
288294 # URLs already reported as missing from the HTTP cache during this run
289295 self ._offline_cache_misses_warned : set [str ] = set ()
296+ # flag set when the validation must be aborted because the metadata
297+ # cannot be read (e.g. the file descriptor is not valid JSON)
298+ self ._aborted : bool = False
299+ self ._abort_reason : str | None = None
290300
291301 # initialize the ROCrate object
292302 if settings .metadata_dict :
@@ -426,6 +436,43 @@ def fail_fast(self) -> bool:
426436 """
427437 return bool (self .settings .abort_on_first )
428438
439+ @property
440+ def aborted (self ) -> bool :
441+ """
442+ Whether the validation has been aborted because the metadata cannot be read.
443+
444+ Unlike :attr:`fail_fast`, this abort is unconditional: when the file descriptor
445+ cannot be parsed (e.g. it is not valid JSON) no metadata can be read, so any
446+ further check would only produce false positives.
447+
448+ :return: ``True`` if the validation has been aborted, ``False`` otherwise
449+ :rtype: bool
450+ """
451+ return self ._aborted
452+
453+ @property
454+ def abort_reason (self ) -> str | None :
455+ """
456+ The reason why the validation has been aborted, if any.
457+ """
458+ return self ._abort_reason
459+
460+ def abort_validation (self , reason : str | None = None ) -> None :
461+ """
462+ Signal that the validation cannot meaningfully continue because the metadata
463+ is unusable (e.g. the file descriptor is not valid JSON).
464+
465+ The check that detects the problem is expected to record its issue first and
466+ then call this method; the validation loop stops as soon as the current
467+ requirement completes, avoiding false positives from checks that depend on
468+ readable metadata.
469+
470+ :param reason: An optional human-readable description of the abort cause
471+ """
472+ self ._aborted = True
473+ self ._abort_reason = reason
474+ logger .debug ("Validation aborted: %s" , reason )
475+
429476 @property
430477 def rel_fd_path (self ) -> Path :
431478 """
0 commit comments