Skip to content

Markdown

Errors

Everything the SDK raises derives from QuickbaseError. Errors that mean a request wasn't sent come first, then the ones for a request that failed. A timed-out write may still have been applied.

The examples below use tasks, made as shown here, and app, which is qb.app("bq1234567"). Job Tasks has Title, Status, Hours, Due Date, Code, which is unique, and Attachment. It starts with three records, and each example starts from those again. A live test runs every example with both clients and checks its output.

from pyquickbase import Quickbase

with Quickbase(
    realm="acme", token="your_user_token"
) as qb:
    tasks = qb.app("bq1234567").table("Job Tasks")
from pyquickbase import AsyncQuickbase

async with AsyncQuickbase(
    realm="acme", token="your_user_token"
) as qb:
    tasks = qb.app("bq1234567").table("Job Tasks")

The base class

For the full picture, see Handling errors.

QuickbaseError

Base class for every exception this library defines.

Example

from pyquickbase import QuickbaseError

try:
    tasks.get(1, select=["No Such Field"])
except QuickbaseError as error:
    print(type(error).__name__)
from pyquickbase import QuickbaseError

try:
    await tasks.get(1, select=["No Such Field"])
except QuickbaseError as error:
    print(type(error).__name__)

Output

UnknownFieldError

Mistakes caught before sending

For the full picture, see Handling errors.

ConfigurationError

The client was given invalid or missing settings.

Inherits from QuickbaseError

Example

from pyquickbase import ConfigurationError

try:
    qb.app("not an app ID")
except ConfigurationError as error:
    print(error)
from pyquickbase import ConfigurationError

try:
    qb.app("not an app ID")
except ConfigurationError as error:
    print(error)

Output

An app ID contains only letters and numbers.

QueryError

A query can't be sent as written, so it wasn't sent to Quickbase.

Inherits from QuickbaseError

Example

from pyquickbase import QueryError

try:
    tasks.count("{7.ex.'Open'}")
except QueryError:
    print("A lowercase operator was refused")
from pyquickbase import QueryError

try:
    await tasks.count("{7.ex.'Open'}")
except QueryError:
    print("A lowercase operator was refused")

Output

A lowercase operator was refused

TooManyRecordsError

More records match a summary than its max_records_scanned lets it read. None were read.

A summary that only counts reads no records, so this is raised only for one that groups, totals, averages, or finds the lowest or highest value.

Inherits from QueryError

Attributes

  • matched int
    How many records match.
  • limit int
    The most records the summary may read.

Example

from pyquickbase import TooManyRecordsError

try:
    tasks.summarize(
        "Status", sum="Hours", max_records_scanned=1
    )
except TooManyRecordsError as error:
    print(error.matched > error.limit, error.limit)
from pyquickbase import TooManyRecordsError

try:
    await tasks.summarize(
        "Status", sum="Hours", max_records_scanned=1
    )
except TooManyRecordsError as error:
    print(error.matched > error.limit, error.limit)

Output

True 1

ConfirmationError

A change needs the confirmation its preview or plan returned, and this one is missing, expired, or for something else. Nothing was changed. Preview or plan again, and show the person the result.

Inherits from QuickbaseError

Example

from pyquickbase import ConfirmationError

update = tasks.operation("update", require_preview=True)
try:
    update.run(
        {"records": [{"Record ID#": 1, "Status": "Done"}]}
    )
except ConfirmationError:
    print("Preview it first")
from pyquickbase import ConfirmationError

update = await tasks.operation("update", require_preview=True)
try:
    await update.run(
        {"records": [{"Record ID#": 1, "Status": "Done"}]}
    )
except ConfirmationError:
    print("Preview it first")

Output

Preview it first

InvalidValueError

A write can't be sent as written, so it wasn't sent to Quickbase.

Inherits from QuickbaseError

Example

from pyquickbase import InvalidValueError

try:
    tasks.insert([{"Record ID#": 1, "Title": "Oops"}])
except InvalidValueError:
    print("Nothing was written")
from pyquickbase import InvalidValueError

try:
    await tasks.insert([{"Record ID#": 1, "Title": "Oops"}])
except InvalidValueError:
    print("Nothing was written")

Output

Nothing was written

FileTooLargeError

A file is over a limit on how much of it may be read, so reading stopped.

Inherits from InvalidValueError

Attributes

  • limit int
    The limit it went over.
  • unit Literal['rows', 'bytes']
    What limit counts: rows, for max_rows, or bytes, for max_unzipped_bytes.

Example

import io

from pyquickbase import FileTooLargeError

try:
    tasks.rows_from_file(
        io.StringIO("Title\nOne\nTwo\n"), max_rows=1
    )
except FileTooLargeError as error:
    print(error.limit, error.unit)
import io

from pyquickbase import FileTooLargeError

try:
    await tasks.rows_from_file(
        io.StringIO("Title\nOne\nTwo\n"), max_rows=1
    )
except FileTooLargeError as error:
    print(error.limit, error.unit)

Output

1 rows

PolicyRefusedError

The client's policy doesn't allow this request, so it wasn't sent.

The message says what was refused, by name, which rule refused it, and what would allow it, without repeating any values from the request. Quickbase's own permissions still apply to whatever the policy allows. A field the policy hides raises UnknownFieldError instead, as if it didn't exist.

Inherits from QuickbaseError

Attributes

  • decision Any
    The Decision, with the rule, the reason, and the tables and fields involved.

Example

from pyquickbase import (
    Quickbase,
    Policy,
    PolicyRefusedError,
)

with Quickbase.from_env(
    policy=Policy.read_only()
) as qb:
    tasks = qb.app("bq1234567").table("bqtasks123")
    try:
        tasks.insert([{"Title": "Paint walls"}])
    except PolicyRefusedError as error:
        print(error.decision.verb, error.decision.layer)
        print(error.decision.reason)
from pyquickbase import (
    AsyncQuickbase,
    Policy,
    PolicyRefusedError,
)

async with AsyncQuickbase.from_env(
    policy=Policy.read_only()
) as qb:
    tasks = qb.app("bq1234567").table("bqtasks123")
    try:
        await tasks.insert([{"Title": "Paint walls"}])
    except PolicyRefusedError as error:
        print(error.decision.verb, error.decision.layer)
        print(error.decision.reason)

Output

insert policy
No rule allows it

Names that don't match

For the full picture, see Handling errors.

UnknownTableError

The app has no table with that name or ID.

Inherits from QuickbaseError

Example

from pyquickbase import UnknownTableError

try:
    app.table("Job Task").info()
except UnknownTableError:
    print("There's no such table")
from pyquickbase import UnknownTableError

try:
    await app.table("Job Task").info()
except UnknownTableError:
    print("There's no such table")

Output

There's no such table

UnknownFieldError

The table has no field with that label or ID.

Inherits from QuickbaseError

Example

from pyquickbase import F, UnknownFieldError

try:
    tasks.count(F("Statuss") == "Open")
except UnknownFieldError as error:
    print(error)
from pyquickbase import F, UnknownFieldError

try:
    await tasks.count(F("Statuss") == "Open")
except UnknownFieldError as error:
    print(error)

Output

This table has no field labeled 'Statuss', or this client can't see it. Did you mean 'Status'?

UnknownReportError

The table has no report with that name or ID, or several reports share the name.

Inherits from QuickbaseError

Example

from pyquickbase import UnknownReportError

try:
    tasks.report("No Such Report").info()
except UnknownReportError:
    print("There's no such report")
from pyquickbase import UnknownReportError

try:
    await tasks.report("No Such Report").info()
except UnknownReportError:
    print("There's no such report")

Output

There's no such report

UnsupportedReportError

The report can't be read as records, such as a summary or chart report.

Inherits from QuickbaseError

Example

from pyquickbase import UnsupportedReportError

try:
    tasks.report("List All").summary_rows()
except UnsupportedReportError:
    print("That's a table report, so use run()")
from pyquickbase import UnsupportedReportError

try:
    await tasks.report("List All").summary_rows()
except UnsupportedReportError:
    print("That's a table report, so use run()")

Output

That's a table report, so use run()

SchemaMismatchError

A table doesn't match what the code expects, so nothing was changed.

An ensure_ method found a field that isn't what it was asked for, or the schema changed since a plan was made.

Inherits from QuickbaseError

Example

from pyquickbase import SchemaMismatchError

try:
    tasks.ensure_field("Title", "numeric")
except SchemaMismatchError:
    print("Title isn't numeric, and wasn't changed")
from pyquickbase import SchemaMismatchError

try:
    await tasks.ensure_field("Title", "numeric")
except SchemaMismatchError:
    print("Title isn't numeric, and wasn't changed")

Output

Title isn't numeric, and wasn't changed

Writes

For the full picture, see Writing records.

WriteError

Part of a write failed, and the rest may have been applied.

When a later batch of a large write fails, __cause__ holds that batch's own error, such as a RateLimitError or RequestTimeoutError.

Inherits from QuickbaseError

Attributes

  • result Any
    A WriteResult with the records that were written and the rows that failed, when Quickbase reported them.

Example

from pyquickbase import WriteError

try:
    tasks.insert([{"Title": "Repeat", "Code": "T-1"}])
except WriteError as error:
    print(error.result.errors[0].reason)
from pyquickbase import WriteError

try:
    await tasks.insert([{"Title": "Repeat", "Code": "T-1"}])
except WriteError as error:
    print(error.result.errors[0].reason)

Output

duplicate

WritePermissionError

A write was refused because of the token's role, so nothing in the failed rows changed.

Quickbase refuses some writes with a 403, and reports others as row errors in a successful response, depending on the role. Both raise this, so except PermissionDeniedError and except WriteError each catch it. result holds what earlier batches or rows did write. If some rows failed for other reasons as well, you get a plain WriteError, whose rows each have a kind.

Inherits from WriteError, PermissionDeniedError

Attributes

  • status_code int
    403 for a refused request, and 207 for row errors.
class WritePermissionError(WriteError, PermissionDeniedError)

SchemaChangeError

A change in a schema plan failed, so the ones after it weren't attempted.

Quickbase can't undo the changes before it, so result says which were made. Planning the same changes again shows only what's left, as the ones made count as already done.

Inherits from WriteError

Attributes

class SchemaChangeError(WriteError)

Responses from Quickbase

For the full picture, see Handling errors.

APIError

Quickbase answered with an unsuccessful status code.

This is the base of the errors for each status, so it's what you catch for any of them.

Inherits from QuickbaseError

Attributes

  • status_code int
    The HTTP status.
  • method str
    The request's HTTP method.
  • path str
    The request's path.
  • message str | None
    Quickbase's wording, when it sent any. It can contain HTML, so escape it before showing it in a web page.
  • description str | None
    Quickbase's further explanation, when it sent any.
  • request_id str | None
    Include this when reporting a problem to Quickbase support.

Example

from pyquickbase import APIError

try:
    qb.request(
        "GET",
        "/tables/bzzzzzzzz",
        params={"appId": "bq1234567"},
    )
except APIError as error:
    print(error.status_code, error.method)
    print(error.message)
from pyquickbase import APIError

try:
    await qb.request(
        "GET",
        "/tables/bzzzzzzzz",
        params={"appId": "bq1234567"},
    )
except APIError as error:
    print(error.status_code, error.method)
    print(error.message)

Output

404 GET
Invalid DBID

BadRequestError

400: Quickbase rejected the request as malformed.

Inherits from APIError

Example

from pyquickbase import BadRequestError

try:
    app.create_table("Job Tasks")
except BadRequestError as error:
    print(error.status_code)
from pyquickbase import BadRequestError

try:
    await app.create_table("Job Tasks")
except BadRequestError as error:
    print(error.status_code)

Output

400

AuthenticationError

401: the token is invalid, or the app or table doesn't exist or is out of the token's reach.

Quickbase gives the same answer for all of these, so this can't say which one happened.

Inherits from APIError

Example

from pyquickbase import AuthenticationError

try:
    qb.app("bzzzzzzzz").info()
except AuthenticationError as error:
    print(error.status_code)
    print(error.message)
from pyquickbase import AuthenticationError

try:
    await qb.app("bzzzzzzzz").info()
except AuthenticationError as error:
    print(error.status_code)
    print(error.message)

Output

401
Access denied

PermissionDeniedError

403: the token's user may not perform this action.

Inherits from APIError

class PermissionDeniedError(APIError)

NotFoundError

404: what was asked for doesn't exist. An app that doesn't exist is a 401 instead.

Inherits from APIError

Example

from pyquickbase import NotFoundError

try:
    tasks.download_file(999, "Attachment")
except NotFoundError as error:
    print(error.status_code)
from pyquickbase import NotFoundError

try:
    await tasks.download_file(999, "Attachment")
except NotFoundError as error:
    print(error.status_code)

Output

404

RateLimitError

429: retries ran out, or Quickbase asked for a longer wait than the retry policy allows.

Inherits from APIError

Attributes

  • retry_after float | None
    The wait Quickbase asked for, in seconds, if it did.
class RateLimitError(APIError)

ServerError

5xx: Quickbase failed to process the request.

Inherits from APIError

class ServerError(APIError)

Connection failures

For the full picture, see Handling errors.

NetworkError

The request failed before a response was received.

Inherits from QuickbaseError

class NetworkError(QuickbaseError)

RequestTimeoutError

The request timed out. A timed-out write may still have been applied.

Inherits from NetworkError

Example

from pyquickbase import (
    Quickbase,
    NetworkError,
    RetryPolicy,
)

no_retries = RetryPolicy(max_retries=0)
with Quickbase.from_env(
    timeout=0.0001, retry=no_retries
) as qb:
    try:
        qb.app("bq1234567").tables()
    except NetworkError as error:
        print(type(error).__name__)
from pyquickbase import (
    AsyncQuickbase,
    NetworkError,
    RetryPolicy,
)

no_retries = RetryPolicy(max_retries=0)
async with AsyncQuickbase.from_env(
    timeout=0.0001, retry=no_retries
) as qb:
    try:
        await qb.app("bq1234567").tables()
    except NetworkError as error:
        print(type(error).__name__)

Output

RequestTimeoutError

InvalidResponseError

Quickbase reported success, but the response body wasn't in the expected format.

Inherits from QuickbaseError

class InvalidResponseError(QuickbaseError)