Context is incorrect when trying to change mode after moving an object to a collection

Hi all,

I really hope this is an easy question. I literally searched for hours now and I just cannot figure this out. I simplified my (quite extensive) code to these lines that throw the error:

import bpy

bpy.ops.object.mode_set(mode = 'OBJECT')

obj = bpy.context.selected_objects[0]

old_colls = obj.users_collection
for coll in old_colls:
    bpy.data.collections[coll.name].objects.unlink(obj)
bpy.data.collections["Final"].objects.link(obj)

bpy.context.area.type = 'VIEW_3D'
print(bpy.context.area.type)
bpy.ops.object.mode_set(mode = 'POSE')

The last line throws:

RuntimeError: Operator bpy.ops.object.mode_set.poll() failed, context is incorrect

mode_set should work in many contexts but I just assured to be in VIEW_3D.

What I also noticed is that, after running the code, I cannot manually change the context mode anymore:
context
It is greyed out.

When I manually select anything in the scene, I can then properly change the mode again. What is happening here?

Thanks!
Nico

well, lets break this down.

you take a selected object and unlink it from its collection.
then you try to link it to some other collection.

before you call the unlink operation, there is a selected object.
but when you have called the unlink operation your object is gone. Basically its deleted, that’s what you have done.

and when you try to link it to the other collection, you try to link “NULL” where an object is expected.
that’s why you get the runtime error.

and the 2nd issue, simply is a Blender feature.
you cannot switch modes when nothing’s there.
start your Blender with its default scene. if you have any objects placed in it delete each of them.
on the blank scene try to switch the mode and you end up exactly at the same point.

Solution.
to copy something from one Collection to an other there is a nice builtin function for.
Which moves all selected objects to a given Collection.

bpy.ops.object.move_to_collection(collection_index = int, is_new = bool, new_collection_name = string)

collection_index = (default= -1) counting from top to bottom. 0 = Scene Collection. 1 = user collection, 2 = …
is_new = (default = False) want to create a new collection
new_collection_name = (default = “”) the Collection’s name if you choosed to create a new one.

hope this helps :smiley:

1 Like

Hi,

first of all: this forum is awesome! I never got replies so quickly. Really appreciated!

Thanks, londo, will try this out asap!
Just some things I want to understand:
The link op actually works when I run the code. So, the object disappears and then reappears in the new collection. It then is still displayed as selected in the Layer View. It is displayed in that darker orange color indicating it is selected but not active. This is probably not intended then.
Also, I thought collections are just grouping views on objects and unlinking objects from them is like removing a user from them, keeping the object, at least in this „before-purge“ userless state.
I did not consider the object as „removed“ because it was literally displayed and selectable after linking it to the collection. Maybe this is not the intended behavior then?

Whatever, thanks a lot. I think I know what is going on now. Will try this out asap (weekend is family time :slight_smile:).

Thanks again!
Nico

Hey Nico,

when you unlink the object it’s not going to be recognized by the Blender context anymore.
What in fact is the core layer for user interactions.

But the object itself is still in Blender’s data structure and you can work with it but not by using the context path.
you would have to take the data path to properly access the object.

bpy.data.objects[‘AnyObjectName’]

use this instead of

bpy.context.selected_objects[0]

after you’d properly linked it up, you end up with the object reassigned to the given collection. and as you said, it’ll be highlighted in a darker orange.
what simply is a selected object but not the active one.

so, basically you’d do:

  1. select the object
  2. unlink it
  3. link it
  4. make active object

essentially what “.move_to_collection” provides you anyway.

at last, why you can link the object anyway.
well, you store the selected_object in a variable and use this to do some actions.
in general any action you’d carry out will affect the original data itself but does not affect the data stored in your variable.
as long as you do not delete, overwrite or reassign the variable or the instance as long you can work with the values in it, even if the original data has changed. that’s why you can link the object up again.

have a nice weekend :wink:

Hey londo,
thanks again. I have it working now. I read somewhere that using bpy.ops should be avoided, so what I was just missing in my code is

bpy.context.view_layer.objects.active = obj

:roll_eyes:

However, I had similar problems elsewhere in my code that I was able to resolve using your explanations.

Thanks!
Nico

hey there,

good to hear that it helps to solve your problem :wink:

well, advices like this make me just shake my head. It’s like to give you a car and wish you a nice ride but have the whole gear train removed in the first place. :crazy_face:

bpy.ops.mesh.primitive_cube_add()

to avoid .ops, would not even let you add a simple cube to your scene, u know.

anyway, happy coding