@@ -244,6 +244,19 @@ class C2paStream(ctypes.Structure):
244244 ]
245245
246246
247+ def _clear_error_state ():
248+ """Clear any existing error state from the C library.
249+
250+ This function should be called at the beginning of object initialization
251+ and before any operations that could potentially raise an error,
252+ to ensure that stale error states from previous operations don't interfere
253+ with new objects being created, or independent function calls.
254+ """
255+ error = _lib .c2pa_error ()
256+ if error :
257+ # Free the error to clear the state
258+ _lib .c2pa_string_free (error )
259+
247260class C2paSignerInfo (ctypes .Structure ):
248261 """Configuration for a Signer."""
249262 _fields_ = [
@@ -264,6 +277,7 @@ def __init__(self, alg, sign_cert, private_key, ta_url):
264277 private_key: The private key as a string
265278 ta_url: The timestamp authority URL as bytes
266279 """
280+ _clear_error_state ()
267281
268282 if sign_cert is None :
269283 raise ValueError ("sign_cert must be set" )
@@ -692,6 +706,8 @@ def load_settings(settings: Union[str, dict], format: str = "json") -> None:
692706 Raises:
693707 C2paError: If there was an error loading the settings
694708 """
709+ _clear_error_state ()
710+
695711 # Convert to JSON string as necessary
696712 try :
697713 if isinstance (settings , dict ):
@@ -776,6 +792,8 @@ def read_ingredient_file(
776792 stacklevel = 2 ,
777793 )
778794
795+ _clear_error_state ()
796+
779797 container = _StringContainer ()
780798
781799 container ._path_str = str (path ).encode ('utf-8' )
@@ -821,6 +839,8 @@ def read_file(path: Union[str, Path],
821839 stacklevel = 2 ,
822840 )
823841
842+ _clear_error_state ()
843+
824844 container = _StringContainer ()
825845
826846 container ._path_str = str (path ).encode ('utf-8' )
@@ -907,6 +927,8 @@ def sign_file(
907927 stacklevel = 2 ,
908928 )
909929
930+ _clear_error_state ()
931+
910932 try :
911933 # Determine if we have a signer or signer info
912934 if isinstance (signer_or_info , C2paSignerInfo ):
@@ -1375,6 +1397,9 @@ def __init__(self,
13751397 C2paError.Encoding: If any of the string inputs
13761398 contain invalid UTF-8 characters
13771399 """
1400+ # Native libs plumbing:
1401+ # Clear any stale error state from previous operations
1402+ _clear_error_state ()
13781403
13791404 self ._closed = False
13801405 self ._initialized = False
@@ -1930,6 +1955,10 @@ def from_info(cls, signer_info: C2paSignerInfo) -> 'Signer':
19301955 Raises:
19311956 C2paError: If there was an error creating the signer
19321957 """
1958+ # Native libs plumbing:
1959+ # Clear any stale error state from previous operations
1960+ _clear_error_state ()
1961+
19331962 signer_ptr = _lib .c2pa_signer_from_info (ctypes .byref (signer_info ))
19341963
19351964 if not signer_ptr :
@@ -2055,6 +2084,10 @@ def wrapped_callback(
20552084 cls ._ERROR_MESSAGES ['encoding_error' ].format (
20562085 str (e )))
20572086
2087+ # Native libs plumbing:
2088+ # Clear any stale error state from previous operations
2089+ _clear_error_state ()
2090+
20582091 # Create the callback object using the callback function
20592092 callback_cb = SignerCallback (wrapped_callback )
20602093
@@ -2095,6 +2128,10 @@ def __init__(self, signer_ptr: ctypes.POINTER(C2paSigner)):
20952128 Raises:
20962129 C2paError: If the signer pointer is invalid
20972130 """
2131+ # Native libs plumbing:
2132+ # Clear any stale error state from previous operations
2133+ _clear_error_state ()
2134+
20982135 # Validate pointer before assignment
20992136 if not signer_ptr :
21002137 raise C2paError ("Invalid signer pointer: pointer is null" )
@@ -2327,6 +2364,7 @@ def from_archive(cls, stream: Any) -> 'Builder':
23272364 """
23282365 builder = cls ({})
23292366 stream_obj = Stream (stream )
2367+
23302368 builder ._builder = _lib .c2pa_builder_from_archive (stream_obj ._stream )
23312369
23322370 if not builder ._builder :
@@ -2352,6 +2390,10 @@ def __init__(self, manifest_json: Any):
23522390 C2paError.Encoding: If manifest JSON contains invalid UTF-8 chars
23532391 C2paError.Json: If the manifest JSON cannot be serialized
23542392 """
2393+ # Native libs plumbing:
2394+ # Clear any stale error state from previous operations
2395+ _clear_error_state ()
2396+
23552397 self ._closed = False
23562398 self ._initialized = False
23572399 self ._builder = None
@@ -2884,6 +2926,8 @@ def format_embeddable(format: str, manifest_bytes: bytes) -> tuple[int, bytes]:
28842926 Raises:
28852927 C2paError: If there was an error converting the manifest
28862928 """
2929+ _clear_error_state ()
2930+
28872931 format_str = format .encode ('utf-8' )
28882932 manifest_array = (ctypes .c_ubyte * len (manifest_bytes ))(* manifest_bytes )
28892933 result_bytes_ptr = ctypes .POINTER (ctypes .c_ubyte )()
@@ -2993,6 +3037,8 @@ def ed25519_sign(data: bytes, private_key: str) -> bytes:
29933037 C2paError: If there was an error signing the data
29943038 C2paError.Encoding: If the private key contains invalid UTF-8 chars
29953039 """
3040+ _clear_error_state ()
3041+
29963042 if not data :
29973043 raise C2paError ("Data to sign cannot be empty" )
29983044
0 commit comments