diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index d360fc4..d265be9 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -5899,8 +5899,8 @@ COPY postgres_log FROM '/full/path/to/logfile.csv' WITH csv;
         <literal>250ms</literal> then all automatic vacuums and analyzes that run
         250ms or longer will be logged.  In addition, when this parameter is
         set to any value other than <literal>-1</literal>, a message will be
-        logged if an autovacuum action is skipped due to the existence of a
-        conflicting lock.  Enabling this parameter can be helpful
+        logged if an autovacuum action is skipped due to a conflicting lock or a
+        concurrently dropped relation.  Enabling this parameter can be helpful
         in tracking autovacuum activity.  This parameter can only be set in
         the <filename>postgresql.conf</filename> file or on the server command line;
         but the setting can be overridden for individual tables by
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 760d191..214b486 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -120,6 +120,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
 	int			elevel;
 	AcquireSampleRowsFunc acquirefunc = NULL;
 	BlockNumber relpages = 0;
+	bool		rel_lock;
 
 	/* Select logging level */
 	if (options & VACOPT_VERBOSE)
@@ -142,6 +143,7 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
 	 * matter if we ever try to accumulate stats on dead tuples.) If the rel
 	 * has been dropped since we last saw it, we don't need to process it.
 	 */
+	rel_lock = true;
 	if (!(options & VACOPT_NOWAIT))
 		onerel = try_relation_open(relid, ShareUpdateExclusiveLock);
 	else if (ConditionalLockRelationOid(relid, ShareUpdateExclusiveLock))
@@ -149,15 +151,51 @@ analyze_rel(Oid relid, RangeVar *relation, int options,
 	else
 	{
 		onerel = NULL;
-		if (relation &&
-			IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
-			ereport(LOG,
+		rel_lock = false;
+	}
+
+	/*
+	 * If we failed to open or lock the relation, emit a log message before
+	 * exiting.
+	 */
+	if (!onerel)
+	{
+		/*
+		 * If the RangeVar is not defined, we do not have enough
+		 * information to provide a meaningful log statement.  Chances
+		 * are that analyze_rel's caller has intentionally not
+		 * provided this information so that this logging is skipped,
+		 * anyway.
+		 */
+		if (relation == NULL)
+			return;
+
+		/*
+		 * Determine the log level.  For autovacuum logs, we emit a LOG
+		 * if log_autovacuum_min_duration is not disabled.  For manual
+		 * ANALYZE, we emit a WARNING to match the log statements in
+		 * the permissions checks.
+		 */
+		if (IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
+			elevel = LOG;
+		else if (!IsAutoVacuumWorkerProcess())
+			elevel = WARNING;
+		else
+			return;
+
+		if (!rel_lock)
+			ereport(elevel,
 					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
 					 errmsg("skipping analyze of \"%s\" --- lock not available",
 							relation->relname)));
-	}
-	if (!onerel)
+		else
+			ereport(elevel,
+					(errcode(ERRCODE_UNDEFINED_TABLE),
+					 errmsg("skipping analyze of \"%s\" --- relation no longer exists",
+							relation->relname)));
+
 		return;
+	}
 
 	/*
 	 * Check permissions --- this should match vacuum's check!
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index cbd6e9b..4fa2300 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -1330,6 +1330,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
 	Oid			save_userid;
 	int			save_sec_context;
 	int			save_nestlevel;
+	bool		rel_lock;
 
 	Assert(params != NULL);
 
@@ -1393,6 +1394,7 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
 	 * If we've been asked not to wait for the relation lock, acquire it first
 	 * in non-blocking mode, before calling try_relation_open().
 	 */
+	rel_lock = true;
 	if (!(options & VACOPT_NOWAIT))
 		onerel = try_relation_open(relid, lmode);
 	else if (ConditionalLockRelationOid(relid, lmode))
@@ -1400,16 +1402,58 @@ vacuum_rel(Oid relid, RangeVar *relation, int options, VacuumParams *params)
 	else
 	{
 		onerel = NULL;
-		if (relation &&
-			IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
-			ereport(LOG,
-					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
-					 errmsg("skipping vacuum of \"%s\" --- lock not available",
-							relation->relname)));
+		rel_lock = false;
 	}
 
+	/*
+	 * If we failed to open or lock the relation, emit a log message before
+	 * exiting.
+	 */
 	if (!onerel)
 	{
+		int elevel;
+
+		/*
+		 * If the RangeVar is not defined, we do not have enough
+		 * information to provide a meaningful log statement.  Chances
+		 * are that vacuum_rel's caller has intentionally not provided
+		 * this information so that this logging is skipped, anyway.
+		 */
+		if (relation == NULL)
+		{
+			PopActiveSnapshot();
+			CommitTransactionCommand();
+			return false;
+		}
+
+		/*
+		 * Determine the log level.  For autovacuum logs, we emit a LOG
+		 * if log_autovacuum_min_duration is not disabled.  For manual
+		 * VACUUM, we emit a WARNING to match the log statements in the
+		 * permissions checks.
+		 */
+		if (IsAutoVacuumWorkerProcess() && params->log_min_duration >= 0)
+			elevel = LOG;
+		else if (!IsAutoVacuumWorkerProcess())
+			elevel = WARNING;
+		else
+		{
+			PopActiveSnapshot();
+			CommitTransactionCommand();
+			return false;
+		}
+
+		if (!rel_lock)
+			ereport(elevel,
+					(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
+					 errmsg("skipping vacuum of \"%s\" --- lock not available",
+							relation->relname)));
+		else
+			ereport(elevel,
+					(errcode(ERRCODE_UNDEFINED_TABLE),
+					 errmsg("skipping vacuum of \"%s\" --- relation no longer exists",
+							relation->relname)));
+
 		PopActiveSnapshot();
 		CommitTransactionCommand();
 		return false;
