Python- Adding menu button to add duplicate of active object at 3D cursor I'm attempting to learn Python, and figured the easiest way to learn would be by studying code snippets, and expanding from there. So to start with, I want to slightly modify the "ui_panel_simple" template so that instead of adding a primitive object at the 3D cursor, it will add a duplicate of the active object at the 3D cursor. 

The full code is as follows:

import bpy


class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Add object duplicate"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = 'PROPERTIES'
    bl_region_type = 'WINDOW'
    bl_context = "object"

    def draw(self, context):
        layout = self.layout

        obj = context.object

        row = layout.row()
        row.label(text="Add duplicate", icon='OBJECT_DATA')

        row = layout.row()
        row.label(text="Active object is: " + obj.name)
        row = layout.row()
        row.prop(obj, "name")

        row = layout.row()
        row.operator("mesh.primitive_cube_add")


def register():
    bpy.utils.register_class(HelloWorldPanel)


def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)


if __name__ == "__main__":
    register()


If I change row.operator("mesh.primitive_cube_add") to row.operator(bpy.ops.object.duplicate(), then I lose the newly added button in the custom panel. I can freely change 'cube" to any primitive object and all works as expected. What am I missing?
For UI layout layout.operator you only need the names after bpy.ops, in your case

        row.operator("object.duplicate")


Always check the system console for error messages if something isn't working

row.operator(bpy.ops.object.duplicate())


will write to system console

Traceback (most recent call last):
 File "/Text", line 32, in draw
 File "/home/batfinger/src/BlenderGIT/qtcreator_build/bin/2.77/scripts/modules/bpy/ops.py", line 189, in __call__
 ret = op_call(self.idname_py(), None, kw)
RuntimeError: Calling operator "bpy.ops.object.duplicate" error, can't modify blend data in this state (drawing/rendering)


If you don't want the panel to show when there is no active_object add a poll method

    @classmethod
    def poll(cls, context):
        return context.active_object is not None


or not as the operator will display as disabled when there is no active object.