diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 640defde860d57a81d0671f2957b99ded15a3566..361ad7b99a52bbbcec570b639800c175d3c19ab7 100644
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
*************** COPY postgres_log FROM '/full/path/to/lo
*** 4670,4679 ****
  
         <para>
          The value for <varname>search_path</varname> must be a comma-separated
!         list of schema names.  If one of the list items is
!         the special value <literal>$user</literal>, then the schema
!         having the name returned by <function>SESSION_USER</> is substituted, if there
!         is such a schema.  (If not, <literal>$user</literal> is ignored.)
         </para>
  
         <para>
--- 4670,4686 ----
  
         <para>
          The value for <varname>search_path</varname> must be a comma-separated
!         list of schema names.  Any name that is not an existing schema, or is
!         a schema for which the user does not have <literal>USAGE</>
!         permission, is silently ignored.
!        </para>
! 
!        <para>
!         If one of the list items is the special name
!         <literal>$user</literal>, then the schema having the name returned by
!         <function>SESSION_USER</> is substituted, if there is such a schema
!         and the user has <literal>USAGE</> permission for it.
!         (If not, <literal>$user</literal> is ignored.)
         </para>
  
         <para>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 4697,4712 ****
  
         <para>
          When objects are created without specifying a particular target
!         schema, they will be placed in the first schema listed
!         in the search path.  An error is reported if the search path is
!         empty.
         </para>
  
         <para>
          The default value for this parameter is
!         <literal>'"$user", public'</literal> (where the second part will be
!         ignored if there is no schema named <literal>public</>).
!         This supports shared use of a database (where no users
          have private schemas, and all share use of <literal>public</>),
          private per-user schemas, and combinations of these.  Other
          effects can be obtained by altering the default search path
--- 4704,4718 ----
  
         <para>
          When objects are created without specifying a particular target
!         schema, they will be placed in the first valid schema named in
!         <varname>search_path</varname>.  An error is reported if the search
!         path is empty.
         </para>
  
         <para>
          The default value for this parameter is
!         <literal>"$user", public</literal>.
!         This setting supports shared use of a database (where no users
          have private schemas, and all share use of <literal>public</>),
          private per-user schemas, and combinations of these.  Other
          effects can be obtained by altering the default search path
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index dc8f8eaf3f3f60f51fd8b59aa78ccfc36e1b23f9..e92efd863ed74fb77425333d772c194c3d36851b 100644
*** a/src/backend/catalog/namespace.c
--- b/src/backend/catalog/namespace.c
*************** ResetTempTableNamespace(void)
*** 3773,3786 ****
   * Routines for handling the GUC variable 'search_path'.
   */
  
! /* check_hook: validate new search_path, if possible */
  bool
  check_search_path(char **newval, void **extra, GucSource source)
  {
- 	bool		result = true;
  	char	   *rawname;
  	List	   *namelist;
- 	ListCell   *l;
  
  	/* Need a modifiable copy of string */
  	rawname = pstrdup(*newval);
--- 3773,3784 ----
   * Routines for handling the GUC variable 'search_path'.
   */
  
! /* check_hook: validate new search_path value */
  bool
  check_search_path(char **newval, void **extra, GucSource source)
  {
  	char	   *rawname;
  	List	   *namelist;
  
  	/* Need a modifiable copy of string */
  	rawname = pstrdup(*newval);
*************** check_search_path(char **newval, void **
*** 3796,3847 ****
  	}
  
  	/*
! 	 * If we aren't inside a transaction, we cannot do database access so
! 	 * cannot verify the individual names.	Must accept the list on faith.
  	 */
- 	if (IsTransactionState())
- 	{
- 		/*
- 		 * Verify that all the names are either valid namespace names or
- 		 * "$user" or "pg_temp".  We do not require $user to correspond to a
- 		 * valid namespace, and pg_temp might not exist yet.  We do not check
- 		 * for USAGE rights, either; should we?
- 		 *
- 		 * When source == PGC_S_TEST, we are checking the argument of an ALTER
- 		 * DATABASE SET or ALTER USER SET command.	It could be that the
- 		 * intended use of the search path is for some other database, so we
- 		 * should not error out if it mentions schemas not present in the
- 		 * current database.  We issue a NOTICE instead.
- 		 */
- 		foreach(l, namelist)
- 		{
- 			char	   *curname = (char *) lfirst(l);
- 
- 			if (strcmp(curname, "$user") == 0)
- 				continue;
- 			if (strcmp(curname, "pg_temp") == 0)
- 				continue;
- 			if (!SearchSysCacheExists1(NAMESPACENAME,
- 									   CStringGetDatum(curname)))
- 			{
- 				if (source == PGC_S_TEST)
- 					ereport(NOTICE,
- 							(errcode(ERRCODE_UNDEFINED_SCHEMA),
- 						   errmsg("schema \"%s\" does not exist", curname)));
- 				else
- 				{
- 					GUC_check_errdetail("schema \"%s\" does not exist", curname);
- 					result = false;
- 					break;
- 				}
- 			}
- 		}
- 	}
  
  	pfree(rawname);
  	list_free(namelist);
  
! 	return result;
  }
  
  /* assign_hook: do extra actions as needed */
--- 3794,3810 ----
  	}
  
  	/*
! 	 * We used to try to check that the named schemas exist, but there are
! 	 * many valid use-cases for having search_path settings that include
! 	 * schemas that don't exist; and often, we are not inside a transaction
! 	 * here and so can't consult the system catalogs anyway.  So now, the only
! 	 * requirement is syntactic validity of the identifier list.
  	 */
  
  	pfree(rawname);
  	list_free(namelist);
  
! 	return true;
  }
  
  /* assign_hook: do extra actions as needed */
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
index d324862049955574a9fda42799e6cb66248688d8..271706d31e9301147ffa85065ff260db2b60730d 100644
*** a/src/test/regress/expected/guc.out
--- b/src/test/regress/expected/guc.out
*************** SELECT current_user = 'temp_reset_user';
*** 605,610 ****
--- 605,635 ----
  
  DROP ROLE temp_reset_user;
  --
+ -- search_path should react to changes in pg_namespace
+ --
+ set search_path = foo, public, not_there_initially;
+ select current_schemas(false);
+  current_schemas 
+ -----------------
+  {public}
+ (1 row)
+ 
+ create schema not_there_initially;
+ select current_schemas(false);
+        current_schemas        
+ ------------------------------
+  {public,not_there_initially}
+ (1 row)
+ 
+ drop schema not_there_initially;
+ select current_schemas(false);
+  current_schemas 
+ -----------------
+  {public}
+ (1 row)
+ 
+ reset search_path;
+ --
  -- Tests for function-local GUC settings
  --
  set work_mem = '3MB';
*************** select report_guc('work_mem'), current_s
*** 617,630 ****
   1MB        | 3MB
  (1 row)
  
! -- this should draw only a warning
! alter function report_guc(text) set search_path = no_such_schema;
! NOTICE:  schema "no_such_schema" does not exist
! -- with error occurring here
! select report_guc('work_mem'), current_setting('work_mem');
! ERROR:  invalid value for parameter "search_path": "no_such_schema"
! DETAIL:  schema "no_such_schema" does not exist
! alter function report_guc(text) reset search_path set work_mem = '2MB';
  select report_guc('work_mem'), current_setting('work_mem');
   report_guc | current_setting 
  ------------+-----------------
--- 642,648 ----
   1MB        | 3MB
  (1 row)
  
! alter function report_guc(text) set work_mem = '2MB';
  select report_guc('work_mem'), current_setting('work_mem');
   report_guc | current_setting 
  ------------+-----------------
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
index 21ed86f26ba259e7258e6b69afa8f8e80e2a2442..0c217923814893d0aacc2c83d548fe778eeaded7 100644
*** a/src/test/regress/sql/guc.sql
--- b/src/test/regress/sql/guc.sql
*************** SELECT current_user = 'temp_reset_user';
*** 183,188 ****
--- 183,200 ----
  DROP ROLE temp_reset_user;
  
  --
+ -- search_path should react to changes in pg_namespace
+ --
+ 
+ set search_path = foo, public, not_there_initially;
+ select current_schemas(false);
+ create schema not_there_initially;
+ select current_schemas(false);
+ drop schema not_there_initially;
+ select current_schemas(false);
+ reset search_path;
+ 
+ --
  -- Tests for function-local GUC settings
  --
  
*************** set work_mem = '1MB';
*** 194,206 ****
  
  select report_guc('work_mem'), current_setting('work_mem');
  
! -- this should draw only a warning
! alter function report_guc(text) set search_path = no_such_schema;
! 
! -- with error occurring here
! select report_guc('work_mem'), current_setting('work_mem');
! 
! alter function report_guc(text) reset search_path set work_mem = '2MB';
  
  select report_guc('work_mem'), current_setting('work_mem');
  
--- 206,212 ----
  
  select report_guc('work_mem'), current_setting('work_mem');
  
! alter function report_guc(text) set work_mem = '2MB';
  
  select report_guc('work_mem'), current_setting('work_mem');
  
