Skip to content

SQLAlchemy Mapper Initialization Error occur when rescan image #7850

@seedspirit

Description

@seedspirit

Summary

After merging PR #7699 (GraphQL legacy code restructuring), SQLAlchemy ORM relationship mapper initialization fails with ArgumentError: Could not locate any relevant foreign key columns when starting the http://Backend.AI Manager.

Steps to Reproduce

  1. Merge PR refactor(BA-3618, BA-3619): Models package refactoring for import isolation #7699 which restructured GraphQL legacy code from models/gql_models/ to api/gql_legacy/
  2. Start the http://Backend.AI Manager application
  3. SQLAlchemy attempts to initialize model relationships during startup
  4. Observe mapper initialization errors

Expected Behavior

All SQLAlchemy ORM relationship mappers should initialize successfully without errors. String-based primaryjoin expressions should correctly resolve referenced classes at runtime.

Actual Behavior

SQLAlchemy mapper initialization fails with errors like:

ArgumentError: Could not locate any relevant foreign key columns for primary join condition 'UserRow.uuid == foreign(VFolderRow.user)' on relationship UserRow.vfolder_rows

The string-based primaryjoin expressions fail to resolve referenced classes because the classes are not available in the runtime namespace when the expressions are evaluated.

Root Cause

Import Path Restructuring Impact:

String-based Primaryjoin Limitation:

  • 33 relationship definitions across 17 model files used string-based primaryjoin parameters
  • Example: primaryjoin="UserRow.uuid == foreign(VFolderRow.user)"
  • SQLAlchemy evaluates these strings at runtime using eval() in the current namespace
  • Referenced classes (e.g., UserRow) must be imported and available in the namespace
  • After PR refactor(BA-3618, BA-3619): Models package refactoring for import isolation #7699's import isolation changes, referenced classes were no longer in namespace during evaluation

Why It Broke:

The import restructuring created stronger module boundaries. When SQLAlchemy tried to evaluate string expressions like "UserRow.uuid == foreign(VFolderRow.user)" in a module that only imported the immediate dependencies, the referenced UserRow class wasn't available in the evaluation namespace.

Solution

Converted all 33 string-based primaryjoin definitions to callable function-based references with lazy imports

Before (String-based):

user = relationship(
      "UserRow",
      primaryjoin="UserRow.uuid == foreign(VFolderRow.user)",
  )

After (Callable function with lazy import):

from sqlalchemy.orm import foreign
  
def _get_user_join_condition():
      from ai.backend.manager.models.user import UserRow
      return UserRow.uuid == foreign(VFolderRow.user)

user = relationship(
      "UserRow",
      primaryjoin=_get_user_join_condition,
  )

Why This Works:

  • Function-based primaryjoin uses lazy evaluation
  • Import happens inside the function, executed when relationship is accessed
  • Classes are imported at usage time, not at definition time
  • Bypasses namespace resolution issues from import isolation

Affected Files (17 files, 33 conversions)

  1. src/ai/backend/manager/models/container_registry/row.py (2)
  2. src/ai/backend/manager/models/association_container_registries_groups/row.py (1)
  3. src/ai/backend/manager/models/group/row.py (3)
  4. src/ai/backend/manager/models/vfolder/row.py (2)
  5. src/ai/backend/manager/models/network/row.py (2)
  6. src/ai/backend/manager/models/notification/row.py (4)
  7. src/ai/backend/manager/models/user/row.py (4)
  8. src/ai/backend/manager/models/endpoint/row.py (4)
  9. src/ai/backend/manager/models/deployment_revision/row.py (3)
  10. src/ai/backend/manager/models/deployment_policy/row.py (1)
  11. src/ai/backend/manager/models/deployment_auto_scaling_policy/row.py (1)
  12. src/ai/backend/manager/models/scaling_group/row.py (1)
  13. src/ai/backend/manager/models/resource_preset/row.py (1)
  14. src/ai/backend/manager/models/routing/row.py (1)
  15. src/ai/backend/manager/models/domain/row.py (1)
  16. src/ai/backend/manager/models/image/row.py (1)
  17. src/ai/backend/manager/models/kernel/row.py (1)

JIRA Issue: BA-3793

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions