From 4735e42fffe6f0fa9c53cc47503126a44c8a7b1a Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 26 Aug 2026 08:07:30 +0000 Subject: [PATCH 1/2] fix: handle fetch target not found errors Co-authored-by: william --- src/linkup/__init__.py | 4 ++++ src/linkup/_client.py | 13 +++++++++++-- src/linkup/_errors.py | 6 ++++++ tests/unit/client_test.py | 13 +++++++++++++ 4 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/linkup/__init__.py b/src/linkup/__init__.py index a6173d1..3699cc3 100644 --- a/src/linkup/__init__.py +++ b/src/linkup/__init__.py @@ -4,6 +4,7 @@ LinkupBudgetLimitExceededError, LinkupFailedFetchError, LinkupFetchResponseTooLargeError, + LinkupFetchTargetNotFoundError, LinkupFetchTargetUnreachableError, LinkupFetchUnsupportedContentTypeError, LinkupFetchUrlIsFileError, @@ -52,6 +53,7 @@ FetchImageExtraction = LinkupFetchImageExtraction FetchResponse = LinkupFetchResponse FetchResponseTooLargeError = LinkupFetchResponseTooLargeError +FetchTargetNotFoundError = LinkupFetchTargetNotFoundError FetchTargetUnreachableError = LinkupFetchTargetUnreachableError FetchUnsupportedContentTypeError = LinkupFetchUnsupportedContentTypeError FetchTask = LinkupFetchTask @@ -93,6 +95,7 @@ "FetchImageExtraction", "FetchResponse", "FetchResponseTooLargeError", + "FetchTargetNotFoundError", "FetchTargetUnreachableError", "FetchTask", "FetchTaskInput", @@ -109,6 +112,7 @@ "LinkupFetchImageExtraction", "LinkupFetchResponse", "LinkupFetchResponseTooLargeError", + "LinkupFetchTargetNotFoundError", "LinkupFetchTargetUnreachableError", "LinkupFetchTask", "LinkupFetchTaskInput", diff --git a/src/linkup/_client.py b/src/linkup/_client.py index 3be5919..4071663 100644 --- a/src/linkup/_client.py +++ b/src/linkup/_client.py @@ -14,6 +14,7 @@ LinkupBudgetLimitExceededError, LinkupFailedFetchError, LinkupFetchResponseTooLargeError, + LinkupFetchTargetNotFoundError, LinkupFetchTargetUnreachableError, LinkupFetchUnsupportedContentTypeError, LinkupFetchUrlIsFileError, @@ -1030,8 +1031,9 @@ def fetch( Raises: LinkupInvalidRequestError: If the provided URL is not valid. - LinkupFailedFetchError: If the provided URL is not found or can't be fetched. + LinkupFailedFetchError: If the provided URL can't be fetched. LinkupFetchResponseTooLargeError: If the fetch response is too large. + LinkupFetchTargetNotFoundError: If the target URL is not found. LinkupFetchTargetUnreachableError: If the target URL cannot be reached. LinkupFetchUnsupportedContentTypeError: If the URL resolves to an unsupported content type. @@ -1090,8 +1092,9 @@ async def async_fetch( Raises: LinkupInvalidRequestError: If the provided URL is not valid. - LinkupFailedFetchError: If the provided URL is not found or can't be fetched. + LinkupFailedFetchError: If the provided URL can't be fetched. LinkupFetchResponseTooLargeError: If the fetch response is too large. + LinkupFetchTargetNotFoundError: If the target URL is not found. LinkupFetchTargetUnreachableError: If the target URL cannot be reached. LinkupFetchUnsupportedContentTypeError: If the URL resolves to an unsupported content type. @@ -1338,6 +1341,12 @@ def _raise_linkup_error(self, response: httpx.Response) -> None: "The provided URL's response is too large to be processed.\n" f"Original error message: {error_msg}." ) + if code == "FETCH_TARGET_NOT_FOUND": + raise LinkupFetchTargetNotFoundError( + "The Linkup API returned a fetch target not found error (400). " + "The target URL was not found.\n" + f"Original error message: {error_msg}." + ) if code == "FETCH_TARGET_UNREACHABLE": raise LinkupFetchTargetUnreachableError( "The Linkup API returned a fetch target unreachable error (400). " diff --git a/src/linkup/_errors.py b/src/linkup/_errors.py index 4890895..7f75cfc 100644 --- a/src/linkup/_errors.py +++ b/src/linkup/_errors.py @@ -82,6 +82,12 @@ class LinkupFetchResponseTooLargeError(Exception): pass +class LinkupFetchTargetNotFoundError(Exception): + """Fetch target not found error, raised when the API reports that the target URL was not found.""" + + pass + + class LinkupFetchTargetUnreachableError(Exception): """Fetch target unreachable error, raised when the Linkup API returns a 400 status code. diff --git a/tests/unit/client_test.py b/tests/unit/client_test.py index 8018d33..1276f24 100644 --- a/tests/unit/client_test.py +++ b/tests/unit/client_test.py @@ -1122,6 +1122,19 @@ async def test_async_fetch( """, linkup.FetchResponseTooLargeError, ), + ( + 400, + b""" + { + "error": { + "code": "FETCH_TARGET_NOT_FOUND", + "message": "The target URL was not found", + "details": [] + } + } + """, + linkup.FetchTargetNotFoundError, + ), ( 400, b""" From d3e5aba366f61ed2a09c2624f74584fbba581a00 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 26 Aug 2026 08:08:36 +0000 Subject: [PATCH 2/2] fix: format fetch target error docs Co-authored-by: william --- src/linkup/_errors.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/linkup/_errors.py b/src/linkup/_errors.py index 7f75cfc..4758ed4 100644 --- a/src/linkup/_errors.py +++ b/src/linkup/_errors.py @@ -83,7 +83,10 @@ class LinkupFetchResponseTooLargeError(Exception): class LinkupFetchTargetNotFoundError(Exception): - """Fetch target not found error, raised when the API reports that the target URL was not found.""" + """Fetch target not found error. + + Raised when the API reports that the target URL was not found. + """ pass