Index: generic/tkButton.c
==================================================================
--- generic/tkButton.c
+++ generic/tkButton.c
@@ -1607,10 +1607,23 @@
     int flags)			/* Information about what happened. */
 {
     register TkButton *butPtr = clientData;
     const char *value;
     Tcl_Obj *valuePtr;
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (butPtr->selVarNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ButtonVarProc, clientData);
+	}
+	return NULL;
+    }
 
     /*
      * If the variable is being unset, then just re-establish the trace unless
      * the whole interpreter is going away.
      */
@@ -1690,18 +1703,31 @@
 	/* ARGSUSED */
 static char *
 ButtonTextVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     TkButton *butPtr = clientData;
     Tcl_Obj *valuePtr;
 
     if (butPtr->flags & BUTTON_DELETED) {
+	return NULL;
+    }
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (butPtr->textVarNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ButtonTextVarProc, clientData);
+	}
 	return NULL;
     }
 
     /*
      * If the variable is unset, then immediately recreate it unless the whole

Index: generic/tkEntry.c
==================================================================
--- generic/tkEntry.c
+++ generic/tkEntry.c
@@ -3133,21 +3133,34 @@
 	/* ARGSUSED */
 static char *
 EntryTextVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Entry *entryPtr = clientData;
     const char *value;
 
     if (entryPtr->flags & ENTRY_DELETED) {
 	/*
 	 * Just abort early if we entered here while being deleted.
 	 */
+	return NULL;
+    }
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (entryPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    EntryTextVarProc, clientData);
+	}
 	return NULL;
     }
 
     /*
      * If the variable is unset, then immediately recreate it unless the whole

Index: generic/tkListbox.c
==================================================================
--- generic/tkListbox.c
+++ generic/tkListbox.c
@@ -3429,18 +3429,31 @@
 
 static char *
 ListboxListVarProc(
     ClientData clientData,	/* Information about button. */
     Tcl_Interp *interp,		/* Interpreter containing variable. */
-    const char *name1,		/* Not used. */
-    const char *name2,		/* Not used. */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Listbox *listPtr = clientData;
     Tcl_Obj *oldListObj, *varListObj;
     int oldLength, i;
     Tcl_HashEntry *entry;
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (listPtr->listVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ListboxListVarProc, clientData);
+	}
+	return NULL;
+    }
 
     /*
      * Bwah hahahaha! Puny mortal, you can't unset a -listvar'd variable!
      */
 

Index: generic/tkMenu.c
==================================================================
--- generic/tkMenu.c
+++ generic/tkMenu.c
@@ -2495,11 +2495,22 @@
     }
 
     menuPtr = mePtr->menuPtr;
 
     if (menuPtr->menuFlags & MENU_DELETION_PENDING) {
-    	return NULL;
+	return NULL;
+    }
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (mePtr->namePtr == NULL) {
+	Tcl_UntraceVar2(interp, name1, name2,
+		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		MenuVarProc, clientData);
+	return NULL;
     }
 
     name = Tcl_GetString(mePtr->namePtr);
 
     /*

Index: generic/tkMenubutton.c
==================================================================
--- generic/tkMenubutton.c
+++ generic/tkMenubutton.c
@@ -878,10 +878,23 @@
     int flags)			/* Information about what happened. */
 {
     register TkMenuButton *mbPtr = clientData;
     const char *value;
     unsigned len;
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (mbPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    MenuButtonTextVarProc, clientData);
+	}
+	return NULL;
+    }
 
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
      */

Index: generic/tkMessage.c
==================================================================
--- generic/tkMessage.c
+++ generic/tkMessage.c
@@ -835,10 +835,23 @@
     const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     register Message *msgPtr = clientData;
     const char *value;
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (msgPtr->textVarName == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    MessageTextVarProc, clientData);
+	}
+	return NULL;
+    }
 
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
      */

Index: generic/tkScale.c
==================================================================
--- generic/tkScale.c
+++ generic/tkScale.c
@@ -1189,10 +1189,23 @@
     register TkScale *scalePtr = clientData;
     const char *resultStr;
     double value;
     Tcl_Obj *valuePtr;
     int result;
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (scalePtr->varNamePtr == NULL) {
+	if (!(flags & TCL_INTERP_DESTROYED)) {
+	    Tcl_UntraceVar2(interp, name1, name2,
+		    TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		    ScaleVarProc, clientData);
+	}
+	return NULL;
+    }
 
     /*
      * If the variable is unset, then immediately recreate it unless the whole
      * interpreter is going away.
      */

Index: generic/ttk/ttkTrace.c
==================================================================
--- generic/ttk/ttkTrace.c
+++ generic/ttk/ttkTrace.c
@@ -24,21 +24,32 @@
  */
 static char *
 VarTraceProc(
     ClientData clientData,	/* Widget record pointer */
     Tcl_Interp *interp, 	/* Interpreter containing variable. */
-    const char *name1,		/* (unused) */
-    const char *name2,		/* (unused) */
+    const char *name1,		/* Name of variable. */
+    const char *name2,		/* Second part of variable name. */
     int flags)			/* Information about what happened. */
 {
     Ttk_TraceHandle *tracePtr = clientData;
     const char *name, *value;
     Tcl_Obj *valuePtr;
 
     if (flags & TCL_INTERP_DESTROYED) {
 	return NULL;
     }
+
+    /*
+     * See ticket [5d991b82].
+     */
+
+    if (tracePtr->varnameObj == NULL) {
+	Tcl_UntraceVar2(interp, name1, name2,
+		TCL_GLOBAL_ONLY|TCL_TRACE_WRITES|TCL_TRACE_UNSETS,
+		VarTraceProc, clientData);
+	return NULL;
+    }
 
     name = Tcl_GetString(tracePtr->varnameObj);
 
     /*
      * If the variable is being unset, then re-establish the trace:

