Skip to content

AttributeError with ChangeState action on 1st button; 'NoneType' object has no attribute 'action_permission_manager' #13

@zedwick

Description

@zedwick

When I have a ChangeState action on the first button (top left) on a StreamDeck+ and load StreamController, the page fails to finish loading with the following error:

2026-02-11 18:21:47.999 | ERROR    | src.backend.DeckManagement.DeckController:load_page:742 - An error has been caught in function 'load_page', process 'MainProcess' (3), thread 'MainThread' (140608720619328):
Traceback (most recent call last):

  File "/app/bin/StreamController/main.py", line 562, in <module>
    main()
    └ <function main at 0x7fe1cb7a72e0>

  File "/app/bin/StreamController/main.py", line 559, in main
    load()
    └ <function load at 0x7fe1cb7a60c0>

  File "/app/bin/StreamController/main.py", line 123, in load
    gl.deck_manager.load_decks()
    │  │            └ <function DeckManager.load_decks at 0x7fe1cbb9a700>
    │  └ <src.backend.DeckManagement.DeckManager.DeckManager object at 0x7fe1c85ab200>
    └ <module 'globals' from '/app/bin/StreamController/globals.py'>

  File "/app/bin/StreamController/src/backend/DeckManagement/DeckManager.py", line 79, in load_decks
    self.load_hardware_decks()
    │    └ <function DeckManager.load_hardware_decks at 0x7fe1cbb9af20>
    └ <src.backend.DeckManagement.DeckManager.DeckManager object at 0x7fe1c85ab200>

  File "/app/bin/StreamController/src/backend/DeckManagement/DeckManager.py", line 92, in load_hardware_decks
    deck_controller = DeckController(self, deck)
                      │              │     └ <StreamDeck.Devices.StreamDeckPlus.StreamDeckPlus object at 0x7fe1c85e7e90>
                      │              └ <src.backend.DeckManagement.DeckManager.DeckManager object at 0x7fe1c85ab200>
                      └ <class 'src.backend.DeckManagement.DeckController.DeckController'>

  File "/app/bin/StreamController/src/backend/DeckManagement/DeckController.py", line 386, in __init__
    self.load_default_page()
    │    └ <function DeckController.load_default_page at 0x7fe1cc9dc400>
    └ <src.backend.DeckManagement.DeckController.DeckController object at 0x7fe1c860c1d0>

  File "/app/bin/StreamController/src/backend/DeckManagement/DeckController.py", line 514, in load_default_page
    self.load_page(page)
    │    │         └ <src.backend.PageManagement.Page.Page object at 0x7fe1c8628f20>
    │    └ <function DeckController.load_page at 0x7fe1cc9dd940>
    └ <src.backend.DeckManagement.DeckController.DeckController object at 0x7fe1c860c1d0>

> File "/app/bin/StreamController/src/backend/DeckManagement/DeckController.py", line 742, in load_page
    self.active_page.initialize_actions()
    │    │           └ <function Page.initialize_actions at 0x7fe1cc9e4c20>
    │    └ <src.backend.PageManagement.Page.Page object at 0x7fe1c8628f20>
    └ <src.backend.DeckManagement.DeckController.DeckController object at 0x7fe1c860c1d0>

  File "/app/bin/StreamController/src/backend/PageManagement/Page.py", line 560, in initialize_actions
    action.on_ready()
    │      └ <function ChangeState.on_ready at 0x7fe1ca5619e0>
    └ <plugins.com_core447_DeckPlugin.main.ChangeState object at 0x7fe1c860f680>

  File "/home/deck/.var/app/com.core447.StreamController/data/plugins/com_core447_DeckPlugin/main.py", line 222, in on_ready
    self.set_media(media_path=os.path.join(self.plugin_base.PATH, "assets", "sidebar.png"), size=0.8)
    │    │                    │  │    │    │    │           └ '/home/deck/.var/app/com.core447.StreamController/data/plugins/com_core447_DeckPlugin'
    │    │                    │  │    │    │    └ <plugins.com_core447_DeckPlugin.main.DeckPlugin object at 0x7fe1c9da5430>
    │    │                    │  │    │    └ <plugins.com_core447_DeckPlugin.main.ChangeState object at 0x7fe1c860f680>
    │    │                    │  │    └ <function join at 0x7fe2040e8d60>
    │    │                    │  └ <module 'posixpath' (frozen)>
    │    │                    └ <module 'os' (frozen)>
    │    └ <function ActionCore.set_media at 0x7fe1cc91cf40>
    └ <plugins.com_core447_DeckPlugin.main.ChangeState object at 0x7fe1c860f680>

  File "/app/bin/StreamController/src/backend/PluginManager/ActionCore.py", line 154, in set_media
    if not self.has_image_control(): return #TODO
           │    └ <function ActionCore.has_image_control at 0x7fe1cc91de40>
           └ <plugins.com_core447_DeckPlugin.main.ChangeState object at 0x7fe1c860f680>

  File "/app/bin/StreamController/src/backend/PluginManager/ActionCore.py", line 403, in has_image_control
    image_control_index = self.get_state().action_permission_manager.get_image_control_index()
                          │    └ <function ActionCore.get_state at 0x7fe1cc91ca40>
                          └ <plugins.com_core447_DeckPlugin.main.ChangeState object at 0x7fe1c860f680>

AttributeError: 'NoneType' object has no attribute 'action_permission_manager'

This seems to only occur when first opening StreamController; I can switch to this page from other pages without issue.

I have 2 states on the button, each with a ChangeState action as the second action. It would only load the first state before it failed with the error. If I remove the ChangeState action from the first state, it would only fail after loading the second state of that button. Removing the action from the second state allows the full page to load.

The workaround: Moving the button from the top left to the top right has solved the problem for me completely.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions