Error Handling¶
Common errors, how to detect them, and recommended handling strategies.
Legacy format¶
Pre-ZIP files use a CArchive binary format. Compatibility samples confirm this
container through SketchUp 2020. skppy.load() decodes its envelope and
CVersionMap. The generated version matrix verifies loading for save targets from
SketchUp 3 through 2020, but an unfamiliar class schema can still be unsupported
even when the container and most of the model are otherwise understood.
import skppy
model = skppy.load("file.skp")
if model.legacy_archive is not None:
print("Legacy archive starts at", model.legacy_archive.archive_offset)
legacy_archive is provenance and diagnostic state. Application code can keep
using model.entities, model.materials, and the other shared collections.
Unsupported class layouts raise an explicit parser exception. Re-save those files as SketchUp 2021 or later when conversion is available.
Strict runtime schemas are listed in the
legacy format reference. Other
known classes are version-aware: their CVersionMap entry and file generation
select the reader. An unregistered runtime class is unsupported even when its
numeric schema matches a known class.
File not found / permission errors¶
skppy.load() calls Python’s built-in open(), so standard Python IOError
/ FileNotFoundError apply:
try:
model = skppy.load("missing.skp")
except FileNotFoundError as exc:
print(f"File does not exist: {exc.filename}")
except PermissionError as exc:
print(f"No read access: {exc.filename}")
Catch these before InvalidSkpError: opening the path failed, so no SKP bytes
were available for format validation.
Corrupt or truncated files¶
When an existing file cannot be decoded as SKP, skppy.load() raises
skppy.InvalidSkpError. Its exception cause retains the low-level failure for
diagnostics. This gives applications one stable error boundary for malformed
modern and legacy input.
Parser-level functions may still raise one of:
Exception |
Cause |
|---|---|
|
The embedded ZIP is corrupt. |
|
A legacy binary primitive is shorter than expected. |
|
A TLV record, string, or required value is malformed. |
|
A UTF-8 string payload is invalid. |
|
A cross-reference (e.g. vertex ID) does not resolve. |
|
A known legacy class uses an unverified schema. |
|
A legacy runtime class has no reader. |
A ZIP container without the required model.dat entry is invalid input and
raises InvalidSkpError; it is not treated as a legacy file or allowed to
leak the lower-level KeyError from zipfile.
Catch the structured legacy errors separately when a user-facing tool can recommend re-saving the file in a newer SketchUp version:
from skppy.parser_legacy import (
UnsupportedLegacyObjectError,
UnsupportedLegacySchemaError,
)
path = "legacy.skp"
try:
model = skppy.load(path)
except (UnsupportedLegacyObjectError, UnsupportedLegacySchemaError) as exc:
# This is a valid legacy container beyond the current class coverage.
print(f"Ask the user to re-save {path!r} in a newer format: {exc}")
except skppy.InvalidSkpError as exc:
# __cause__ retains the low-level parser failure for logs and bug reports.
print(f"Could not decode {path!r}: {exc}")
print(f"Underlying error: {exc.__cause__!r}")
OldFormatError is an internal dispatch signal from the ZIP header reader. A
normal skppy.load() call detects the CArchive container first and does not
raise it merely because the input is a supported legacy file.
Write/export status¶
skppy.save() raises NotImplementedError when a shared legacy-only field has
no confirmed modern representation. The destination remains untouched because
serialization completes in memory first. The Blender exporter reports
unsupported Blender object families and conversion warnings in the operator
result.
try:
skppy.save(model, "output.skp")
except NotImplementedError as exc:
print(f"This model cannot be represented without loss: {exc}")
Validation errors such as duplicate IDs or dangling references are reported as
ValueError. In either case, serialization fails before replacing an existing
destination.
Common pitfalls¶
Duplicate material names¶
If two materials share the same name, model.get_material(name) returns only
the first one. Use unique names when creating materials.
Coordinate units¶
All positions in skppy are in inches. Forgetting to convert can produce
models that are 39.37x too large or too small:
INCHES = 1.0
MM = 1.0 / 25.4 # 1 mm in inches
CM = 1.0 / 2.54
vertex = e.add_vertex(500 * MM, 0, 0) # 500 mm ~= 19.69 inches
Apply the conversion to positions and physical texture scales. Direction vectors, normalized factors, and angles are unitless.
Faces with no vertices¶
If face.triangulate(entities) returns an empty list, the face is degenerate
(fewer than 3 unique non-collinear vertices). This is normal for some
SketchUp models that contain zero-area faces used as construction geometry.
Nested instances not flattened¶
model.entities only contains root-level objects. Nested instances inside
definitions are in definition.entities. Always recurse to find all geometry.
See guides/components.md for a recursive walker.