Scheduler Fails with ModuleNotFoundError: No module named 'modia_core'

Hi Frappe Community,

We’re using a custom app named modia_core on both our DEV and PROD servers (ERPNext v15.17.0, Frappe v15.17.0). Everything is working well — including custom DocTypes, REST APIs, server/client scripts, and hooks — except the background scheduler. we would like to confirm proper directory structure.

We’re seeing this persistent scheduler error:

ModuleNotFoundError: No module named ‘modia_core’

But the module definitely exists — we can run this just fine manually:
import modia_core.api.amazon_sync
modia_core.api.amazon_sync.pull_orders()

apps/modia_core/
├── README.md
├── init.py
├── license.txt
├── modia_core/ # ← 1st level
│ ├── init.py
│ ├── hooks.py
│ ├── modules.txt
│ ├── api/
│ ├── fixtures/
│ ├── …
│ ├── modia_core/ # ← :warning: 2nd nested
│ │ ├── init.py
│ │ ├── doctype/
│ │ ├── report/
│ │ └── workspace/

Yes — the real custom DocTypes and workspace files are inside a third-level directory:

apps/modia_core/modia_core/modia_core/ # ← This is the 3rd level

scheduler_events = {
“cron”: {
“*/2 * * * ": “modia_core.api.amazon_sync.pull_orders”,
"
/3 * * * *”: “modia_core.api.marketplace_to_sales_order.create_sales_orders_from_marketplace”
}
}

But the same function runs fine manually using:

bench --site mysite execute modia_core.api.amazon_sync.pull_orders


:question: Our Questions

  1. :white_check_mark: What is the correct folder structure for a custom app like modia_core?
  2. :white_check_mark: Should we remove the extra modia_core/modia_core/modia_core layer and consolidate all logic inside the 2nd level?
  3. :white_check_mark: Do we need to rename or flatten directories and then update all references (hooks, scripts, etc.)?
  4. :white_check_mark: Is sys.path.append() in init.py masking the real issue?
  5. :white_check_mark: What is the correct fix to get scheduler imports working — without breaking existing server/client script paths?

We want to fix this the right way on both DEV and PROD. Appreciate guidance from Frappe maintainers or anyone who’s tackled this issue before.

MODIA Dev Team