| name | troubleshooting |
| description | Diagnose and fix common Cartography intel-module errors — `ModuleNotFoundError`, `PropertyRef validation failed`, `GraphJob failed`, missing relationships, MatchLink misses, cleanup deleting too much, slow queries, ignored custom schema fields, key errors during transform. Use when the user reports an error while developing or running a Cartography module. |
troubleshooting
Diagnostic playbook for the most common errors encountered while developing Cartography intel modules.
Common issues and solutions
Import errors
cartography/intel/your_service/__init__.py
cartography/models/your_service/__init__.py
Checklist:
Schema validation errors
@dataclass(frozen=True)
class YourNodeProperties(CartographyNodeProperties):
id: PropertyRef = PropertyRef("id")
lastupdated: PropertyRef = PropertyRef("lastupdated", set_in_kwargs=True)
Common causes:
- Missing
frozen=True in @dataclass.
- Missing type annotation (
: PropertyRef).
- Typo in the
PropertyRef field name.
Relationship connection issues
load(neo4j_session, TenantSchema(), tenant_data, lastupdated=update_tag)
load(neo4j_session, UserSchema(), user_data, lastupdated=update_tag, TENANT_ID=tenant_id)
Debugging steps:
- Check the target node label matches exactly.
- Verify
target_node_matcher keys match the target node's property names.
- Ensure the value in your data dict or kwargs is not
None.
Cleanup job failures
common_job_parameters = {
"UPDATE_TAG": config.update_tag,
"TENANT_ID": tenant_id,
}
@dataclass(frozen=True)
class MySchema(CartographyNodeSchema):
scoped_cleanup: bool = False
For details on when to override scoped_cleanup, see the add-node-type skill.
Data transform issues
{
"id": data["id"],
"name": data.get("name"),
"email": data.get("email"),
}
Schema definition issues
@dataclass(frozen=True)
class MyRel(CartographyRelSchema):
target_node_label: str = "TargetNode"
target_node_matcher: TargetNodeMatcher = make_target_node_matcher(...)
direction: LinkDirection = LinkDirection.OUTWARD
rel_label: str = "CONNECTS_TO"
properties: MyRelProperties = MyRelProperties()
For the standard schema fields, see the add-node-type skill.
Performance issues
email: PropertyRef = PropertyRef("email", extra_index=True)
MATCH (u:User {id: $user_id})
MATCH (u:User {name: $name})
Fields used inside a target_node_matcher are indexed automatically.
MatchLink issues
load(neo4j_session, SourceNodeSchema(), source_data, ...)
load(neo4j_session, TargetNodeSchema(), target_data, ...)
load_matchlinks(
neo4j_session,
YourMatchLinkSchema(),
mapping_data,
lastupdated=update_tag,
_sub_resource_label="AWSAccount",
_sub_resource_id=account_id,
)
GraphJob.from_matchlink(
YourMatchLinkSchema(),
"AWSAccount",
common_job_parameters["AWS_ID"],
common_job_parameters["UPDATE_TAG"],
).run(neo4j_session)
For full MatchLink details, see the add-relationship skill.
Debugging tips
- Check existing patterns first. Look at similar modules in
cartography/intel/ before inventing new ones.
- Verify imports. All
CartographyNodeSchema / CartographyRelSchema imports must point to cartography.models.core.*.
- Test transform functions with real API responses.
- Validate Cypher in Neo4j Browser when relationships are not appearing.
- Check file naming. Module files should match the service name (
cartography/intel/lastpass/users.py).
- Run tests incrementally. After each change, run the integration test.
- Test through
sync(), not isolated load() calls.
Key files
| File | Purpose |
|---|
cartography/client/core/tx.py | Core load() and load_matchlinks() — query generation lives here |
cartography/graph/job.py | GraphJob cleanup operations |
cartography/models/core/common.py | PropertyRef definition |
cartography/models/core/nodes.py | CartographyNodeSchema, CartographyNodeProperties, ExtraNodeLabels, etc. |
cartography/models/core/relationships.py | CartographyRelSchema, LinkDirection, matchers, MatchLinks |
cartography/config.py | Config object — check missing fields here |
cartography/cli.py | Typer CLI with help panels |
cartography/data/indexes.cypher | Manual index definitions (legacy) |
cartography/data/jobs/cleanup/ | Legacy cleanup JSON files |
cartography/data/jobs/analysis/ | Global analysis JSON files (see analysis-jobs skill) |
cartography/data/jobs/scoped_analysis/ | Scoped analysis JSON files |
Test utilities
from tests.integration.util import check_nodes, check_rels
expected_nodes = {
("user-123", "alice@example.com"),
("user-456", "bob@example.com"),
}
assert check_nodes(neo4j_session, "YourServiceUser", ["id", "email"]) == expected_nodes
expected_rels = {
("user-123", "tenant-123"),
("user-456", "tenant-123"),
}
assert check_rels(
neo4j_session,
"YourServiceUser", "id",
"YourServiceTenant", "id",
"RESOURCE",
rel_direction_right=True,
) == expected_rels
Error message reference
| Error message | Likely cause | Solution |
|---|
PropertyRef validation failed | Missing type annotation or frozen=True | Check dataclass definition |
Node not found for relationship | Target node does not exist | Load parent nodes first |
GraphJob failed | Wrong common_job_parameters | Check UPDATE_TAG and tenant ID |
KeyError: 'field_name' | Required field missing in API response | Use .get() for optional fields |
ModuleNotFoundError | Missing __init__.py | Add __init__.py to all directories |
Relationship not created | Matcher property mismatch | Verify property names match exactly |
When to ask for help
Stop and ask the user when:
- Legacy Cypher queries contain unclear business logic.
- Complex relationships do not map clearly to the data model.
- Tests keep failing after multiple attempts.
- Multiple modules look interdependent.
- Performance issues persist after adding indexes.
- The graph contains unexpected data after sync.